From 8a1eeed193c86f033b4a30e5fe44270f56858ee6 Mon Sep 17 00:00:00 2001 From: Mine Starks Date: Thu, 9 May 2024 10:21:10 -0700 Subject: [PATCH 1/5] (circuits) add circuit_vis directory --- circuit_vis/.eslintignore | 5 + circuit_vis/.eslintrc.cjs | 23 + circuit_vis/.gitattributes | 62 + circuit_vis/.github/PULL_REQUEST_TEMPLATE.md | 30 + circuit_vis/.github/workflows/constraints.txt | 5 + circuit_vis/.github/workflows/main.yml | 52 + .../.github/workflows/tests_python.yml | 129 + circuit_vis/.gitignore | 156 + circuit_vis/.prettierrc.js | 17 + circuit_vis/README.md | 94 + circuit_vis/SECURITY.md | 41 + .../__snapshots__/gateFormatter.test.ts.snap | 2991 +++++++++++++++++ .../__snapshots__/inputFormatter.test.ts.snap | 170 + .../registerFormatter.test.ts.snap | 1786 ++++++++++ circuit_vis/__tests__/gateFormatter.test.ts | 1010 ++++++ circuit_vis/__tests__/inputFormatter.test.ts | 84 + circuit_vis/__tests__/process.test.ts | 2663 +++++++++++++++ .../__tests__/registerFormatter.test.ts | 165 + circuit_vis/__tests__/utils.test.ts | 51 + circuit_vis/example/circuits.js | 1671 +++++++++ circuit_vis/example/index.html | 58 + circuit_vis/example/script.js | 29 + circuit_vis/jest.config.js | 8 + circuit_vis/package.json | 53 + circuit_vis/src/circuit.ts | 72 + circuit_vis/src/constants.ts | 39 + circuit_vis/src/formatters/formatUtils.ts | 177 + circuit_vis/src/formatters/gateFormatter.ts | 467 +++ circuit_vis/src/formatters/inputFormatter.ts | 68 + .../src/formatters/registerFormatter.ts | 104 + circuit_vis/src/index.ts | 30 + circuit_vis/src/metadata.ts | 56 + circuit_vis/src/process.ts | 453 +++ circuit_vis/src/register.ts | 41 + circuit_vis/src/sqore.ts | 351 ++ circuit_vis/src/styles.ts | 236 ++ circuit_vis/src/utils.ts | 62 + circuit_vis/tsconfig.json | 17 + circuit_vis/webpack.config.js | 71 + 39 files changed, 13597 insertions(+) create mode 100644 circuit_vis/.eslintignore create mode 100644 circuit_vis/.eslintrc.cjs create mode 100644 circuit_vis/.gitattributes create mode 100644 circuit_vis/.github/PULL_REQUEST_TEMPLATE.md create mode 100644 circuit_vis/.github/workflows/constraints.txt create mode 100644 circuit_vis/.github/workflows/main.yml create mode 100644 circuit_vis/.github/workflows/tests_python.yml create mode 100644 circuit_vis/.gitignore create mode 100644 circuit_vis/.prettierrc.js create mode 100644 circuit_vis/README.md create mode 100644 circuit_vis/SECURITY.md create mode 100644 circuit_vis/__tests__/__snapshots__/gateFormatter.test.ts.snap create mode 100644 circuit_vis/__tests__/__snapshots__/inputFormatter.test.ts.snap create mode 100644 circuit_vis/__tests__/__snapshots__/registerFormatter.test.ts.snap create mode 100644 circuit_vis/__tests__/gateFormatter.test.ts create mode 100644 circuit_vis/__tests__/inputFormatter.test.ts create mode 100644 circuit_vis/__tests__/process.test.ts create mode 100644 circuit_vis/__tests__/registerFormatter.test.ts create mode 100644 circuit_vis/__tests__/utils.test.ts create mode 100644 circuit_vis/example/circuits.js create mode 100644 circuit_vis/example/index.html create mode 100644 circuit_vis/example/script.js create mode 100644 circuit_vis/jest.config.js create mode 100644 circuit_vis/package.json create mode 100644 circuit_vis/src/circuit.ts create mode 100644 circuit_vis/src/constants.ts create mode 100644 circuit_vis/src/formatters/formatUtils.ts create mode 100644 circuit_vis/src/formatters/gateFormatter.ts create mode 100644 circuit_vis/src/formatters/inputFormatter.ts create mode 100644 circuit_vis/src/formatters/registerFormatter.ts create mode 100644 circuit_vis/src/index.ts create mode 100644 circuit_vis/src/metadata.ts create mode 100644 circuit_vis/src/process.ts create mode 100644 circuit_vis/src/register.ts create mode 100644 circuit_vis/src/sqore.ts create mode 100644 circuit_vis/src/styles.ts create mode 100644 circuit_vis/src/utils.ts create mode 100644 circuit_vis/tsconfig.json create mode 100644 circuit_vis/webpack.config.js diff --git a/circuit_vis/.eslintignore b/circuit_vis/.eslintignore new file mode 100644 index 0000000000..823d7d2d02 --- /dev/null +++ b/circuit_vis/.eslintignore @@ -0,0 +1,5 @@ +coverage/ +dist/ +lib/ +node_modules/ +*.config.js diff --git a/circuit_vis/.eslintrc.cjs b/circuit_vis/.eslintrc.cjs new file mode 100644 index 0000000000..23abbbdca7 --- /dev/null +++ b/circuit_vis/.eslintrc.cjs @@ -0,0 +1,23 @@ +module.exports = { + parser: '@typescript-eslint/parser', // Specifies the ESLint parser + parserOptions: { + ecmaVersion: 2019, // Allows for the parsing of modern ECMAScript features + sourceType: 'module', // Allows for the use of imports + }, + extends: [ + 'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin + 'prettier/@typescript-eslint', // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier + 'plugin:prettier/recommended', // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. + ], + plugins: ['jest'], + rules: { + // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs + // e.g. "@typescript-eslint/explicit-function-return-type": "off", + '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '_' }], + 'jest/no-disabled-tests': 'warn', + 'jest/no-focused-tests': 'error', + 'jest/no-identical-title': 'error', + 'jest/prefer-to-have-length': 'warn', + 'jest/valid-expect': 'error', + }, +}; diff --git a/circuit_vis/.gitattributes b/circuit_vis/.gitattributes new file mode 100644 index 0000000000..02f83ee3b0 --- /dev/null +++ b/circuit_vis/.gitattributes @@ -0,0 +1,62 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto +*.sh text +*.md text + +############################################################################### +# diff behavior for some non-binary formats +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.md diff=astextplain +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/circuit_vis/.github/PULL_REQUEST_TEMPLATE.md b/circuit_vis/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000000..ad90d6fe5a --- /dev/null +++ b/circuit_vis/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,30 @@ +# Description + +Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. If applicable, include a screenshot that showcase your changes. + +Fixes # (issue) + +## Type of change + +Please delete options that are not relevant. + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] This change requires a documentation update + +# How Has This Been Tested? + +Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration + +- [ ] Test A +- [ ] Test B + +# Checklist: + +- [ ] My code follows the style guidelines of this project +- [ ] I have performed a self-review of my own code +- [ ] I have commented my code, particularly in hard-to-understand areas +- [ ] I have made corresponding changes to the documentation +- [ ] My changes generate no new warnings +- [ ] Any dependent changes have been merged and published in downstream modules diff --git a/circuit_vis/.github/workflows/constraints.txt b/circuit_vis/.github/workflows/constraints.txt new file mode 100644 index 0000000000..7f9f429f19 --- /dev/null +++ b/circuit_vis/.github/workflows/constraints.txt @@ -0,0 +1,5 @@ +pip==21.1.3 +nox==2021.6.12 +nox-poetry==0.8.6 +poetry==1.1.7 +virtualenv==20.6.0 diff --git a/circuit_vis/.github/workflows/main.yml b/circuit_vis/.github/workflows/main.yml new file mode 100644 index 0000000000..26eee627dc --- /dev/null +++ b/circuit_vis/.github/workflows/main.yml @@ -0,0 +1,52 @@ +name: CI + +on: + # Triggers the workflow on all PRs and push events to the main branch + pull_request: + push: + branches: [ main ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Runs jobs in parallel +jobs: + build: + runs-on: ubuntu-latest + + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + + - name: Install dependencies + run: npm install + + - name: Build TypeScript + run: npm run build + + - name: Build package for production with Webpack + run: npm run build:prod + + test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Install dependencies + run: npm install + + - name: Run tests with Jest + run: npm test + + lint: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Install dependencies + run: npm install + + - name: Lint project with ESLint + run: npm run lint diff --git a/circuit_vis/.github/workflows/tests_python.yml b/circuit_vis/.github/workflows/tests_python.yml new file mode 100644 index 0000000000..e446c0598b --- /dev/null +++ b/circuit_vis/.github/workflows/tests_python.yml @@ -0,0 +1,129 @@ +name: Python Tests + +on: + # Triggers the workflow on all PRs and push events to the main branch + pull_request: + push: + branches: [ main ] + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +jobs: + tests: + name: ${{ matrix.session }} ${{ matrix.python-version }} / ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - { python-version: 3.9, os: ubuntu-latest, session: "pre-commit" } + - { python-version: 3.9, os: ubuntu-latest, session: "flake8" } + - { python-version: 3.9, os: ubuntu-latest, session: "mypy" } + - { python-version: 3.9, os: ubuntu-latest, session: "safety" } + - { python-version: 3.9, os: ubuntu-latest, session: "typeguard" } + - { python-version: 3.9, os: ubuntu-latest, session: "tests" } + - { python-version: 3.8, os: ubuntu-latest, session: "tests" } + - { python-version: 3.9, os: windows-latest, session: "tests" } + - { python-version: 3.9, os: macos-latest, session: "tests" } + - { python-version: 3.9, os: ubuntu-latest, session: "build"} + + env: + NOXSESSION: ${{ matrix.session }} + + steps: + - name: Check out the repository + uses: actions/checkout@v2.3.4 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2.2.2 + with: + python-version: ${{ matrix.python-version }} + + - name: Upgrade pip + run: | + pip install --constraint=.github/workflows/constraints.txt pip + pip --version + + - name: Install Poetry + run: | + pip install --constraint=.github/workflows/constraints.txt poetry + poetry --version + + - name: Install Nox + run: | + pip install --constraint=.github/workflows/constraints.txt nox nox-poetry + nox --version + + - name: Compute pre-commit cache key + if: matrix.session == 'pre-commit' + id: pre-commit-cache + shell: python + run: | + import hashlib + import sys + + python = "py{}.{}".format(*sys.version_info[:2]) + payload = sys.version.encode() + sys.executable.encode() + digest = hashlib.sha256(payload).hexdigest() + result = "${{ runner.os }}-{}-{}-pre-commit".format(python, digest[:8]) + + print("::set-output name=result::{}".format(result)) + + - name: Restore pre-commit cache + uses: actions/cache@v2.1.6 + if: matrix.session == 'pre-commit' + with: + path: ~/.cache/pre-commit + key: ${{ steps.pre-commit-cache.outputs.result }}-${{ hashFiles('.pre-commit-config.yaml') }} + restore-keys: | + ${{ steps.pre-commit-cache.outputs.result }}- + + - name: Run Nox + if: matrix.session != 'build' + run: | + nox --force-color --python=${{ matrix.python-version }} + working-directory: quantum-viz + + - name: Upload coverage data + if: always() && matrix.session == 'tests' + uses: "actions/upload-artifact@v2.2.4" + with: + name: coverage-data + path: "quantum-viz/.coverage.*" + + - name: Combine coverage data and display human readable report + if: always() && matrix.session == 'tests' + run: | + nox --force-color --session=coverage + working-directory: quantum-viz + + - name: Create coverage report + if: always() && matrix.session == 'tests' + run: | + nox --force-color --session=coverage -- xml + working-directory: quantum-viz + + - name: Upload coverage report + if: always() && matrix.session == 'tests' + uses: codecov/codecov-action@v1.5.2 + + - name: Bump version for developmental release + if: "matrix.session == 'build'" + run: | + poetry version patch && + version=$(poetry version | awk '{ print $2 }') && + poetry version $version.dev.$(date +%s) + working-directory: quantum-viz + + - name: Build package + if: matrix.session == 'build' + run: | + poetry build --ansi + working-directory: quantum-viz + + - name: Upload quantum-viz dist + if: matrix.session == 'build' + uses: actions/upload-artifact@v2.2.4 + with: + name: dist + path: quantum-viz/dist/* diff --git a/circuit_vis/.gitignore b/circuit_vis/.gitignore new file mode 100644 index 0000000000..34a3ea2900 --- /dev/null +++ b/circuit_vis/.gitignore @@ -0,0 +1,156 @@ +## Ignore Node.js temporary files, build results, and +## files generated by popular Node.js add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/Node.gitignore + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env.test +.*[v]env/ + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + + +## Project-specific files ## + +# NPM's package-lock.json +package-lock.json + +# VSCode configuration +.vscode + +# IntelliJ +.idea + +# macOS metadata folder +.DS_Store + +# Compiled files +lib +.tgz + +# Python +.mypy_cache/ +*/.coverage +*/.coverage.* +*/.nox/ +*/.python-version +*/.pytype/ +/dist/ +*/docs/_build/ +/src/*.egg-info/ +__pycache__/ +*/.cookiecutter.json +*-checkpoint.ipynb +*/*.xml +*.xml diff --git a/circuit_vis/.prettierrc.js b/circuit_vis/.prettierrc.js new file mode 100644 index 0000000000..9d3becd4b7 --- /dev/null +++ b/circuit_vis/.prettierrc.js @@ -0,0 +1,17 @@ +module.exports = { + semi: true, + trailingComma: 'all', + singleQuote: true, + endOfLine: 'lf', + printWidth: 120, + tabWidth: 4, + parser: 'typescript', + overrides: [ + { + files: ['*.md', '*.json', '*.yml', '*.yaml'], + options: { + tabWidth: 2, + }, + }, + ], +}; diff --git a/circuit_vis/README.md b/circuit_vis/README.md new file mode 100644 index 0000000000..f3e9cd2222 --- /dev/null +++ b/circuit_vis/README.md @@ -0,0 +1,94 @@ +# quantum-viz.js +[![Licensed under the MIT License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE.txt) +[![PR's Welcome](https://img.shields.io/badge/PRs%20-welcome-brightgreen.svg)](CONTRIBUTING.md) +[![Build Status](https://github.com/microsoft/quantum-viz.js/actions/workflows/main.yml/badge.svg)](https://github.com/microsoft/quantum-viz.js/actions) +[![npm version](https://badge.fury.io/js/%40microsoft%2Fquantum-viz.js.svg)](https://www.npmjs.com/package/@microsoft/quantum-viz.js) + +

+ screenshot of circuit generated by quantum-viz +

+ +**quantum-viz.js** (or **qviz**) is a configurable tool for rendering quantum circuits. With the increasing demand for quantum libraries and educational tools, quantum circuits provide an intuitive way to visualize and understand quantum algorithms. quantum-viz.js is a lightweight library that can be easily integrated into any project. It aims to be easily configurable while allowing complex user interactions, such as toggling between different measurement outcomes. + +## Getting Started +### Installation +Include `quantum-viz.js` in your HTML page by using it directly from CDN: +```html + +``` +or import it in into your TypeScript package: +```bash +npm i @microsoft/quantum-viz.js +``` + +### Usage +1. Create a `Circuit` JavaScript object (the `Circuit` schema is documented [here](https://github.com/microsoft/quantum-viz.js/wiki/API-schema-reference)): +```js +const sampleCircuit = { + qubits: [ + // ... + ], + operations: [ + // ... + ], +}; +``` + + +2. Draw it in a `div`: +```js +const sampleDiv = document.getElementById('sample'); +qviz.draw(sampleCircuit, sampleDiv, qviz.STYLES['Default']); +``` + +Refer to the [`example`](./example) folder for an example on how to use quantum-viz.js. Notice that in order to open the contents of this folder in a browser you will need first to install from source (see [below](#running-from-source)). + +## Python usage + +To use this package with Python, use [quantum-viz](/quantum-viz). + +## Running from source + +### Installing +To build and install this project from source, run the following commands from the root folder of this repository: +```bash +# Install dependencies +> npm install +# Build +> npm run build:prod +``` + +### Running tests +To run tests for this project, run the following commands: +```bash +# Installs dependencies (run this step if you haven't) +> npm install +# Starts Jest tests +> npm run test +``` + +## Contributing +Check out our [contributing guidelines](CONTRIBUTING.md) to find out how you can contribute to quantum-viz.js! + + +## Feedback ## +If you have feedback about this library, please let us know by filing a [new issue](https://github.com/microsoft/quantum-viz.js/issues/new/choose)! + + +## Reporting Security Issues +Security issues and bugs should be reported privately, via email, to the Microsoft Security +Response Center (MSRC) at [secure@microsoft.com](mailto:secure@microsoft.com). You should +receive a response within 24 hours. If for some reason you do not, please follow up via +email to ensure we received your original message. Further information, including the +[MSRC PGP](https://technet.microsoft.com/en-us/security/dn606155) key, can be found in +the [Security TechCenter](https://technet.microsoft.com/en-us/security/default). + + +## Trademarks +This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft's Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies. + + +## Code of Conduct +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/circuit_vis/SECURITY.md b/circuit_vis/SECURITY.md new file mode 100644 index 0000000000..f0c2dc14f4 --- /dev/null +++ b/circuit_vis/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + + * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). + + diff --git a/circuit_vis/__tests__/__snapshots__/gateFormatter.test.ts.snap b/circuit_vis/__tests__/__snapshots__/gateFormatter.test.ts.snap new file mode 100644 index 0000000000..e75b6f54d1 --- /dev/null +++ b/circuit_vis/__tests__/__snapshots__/gateFormatter.test.ts.snap @@ -0,0 +1,2991 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Testing _classicalControlled No htmlClass 1`] = ` + + + + + + + + + X + + + + + + + + + + + ? + + + + +`; + +exports[`Testing _classicalControlled change padding 1`] = ` + + + + + + + + + X + + + + + + + + + + + ? + + + + +`; + +exports[`Testing _classicalControlled multiple 'zero'/'one' children 1`] = ` + + + + + + + + X + + + + + + + + + + Z + + + + + + + + + + + + H + + + + + + + + + + + ? + + + + +`; + +exports[`Testing _classicalControlled nested children 1`] = ` + + + + + + + + + X + + + + + + + + + + + + + + + + + + + + + + + ? + + + + + + + + + + + ? + + + + +`; + +exports[`Testing _classicalControlled one 'one' child 1`] = ` + + + + + + + + + X + + + + + + + + + + + ? + + + + +`; + +exports[`Testing _classicalControlled one 'zero' child 1`] = ` + + + + + + + + X + + + + + + + + + + + + ? + + + + +`; + +exports[`Testing _classicalControlled one 'zero'/'one' child 1`] = ` + + + + + + + + X + + + + + + + + + + + + H + + + + + + + + + + + ? + + + + +`; + +exports[`Testing _controlledGate CNOT gate 1`] = ` + + + + + + + + + +`; + +exports[`Testing _controlledGate CNOT gate 2`] = ` + + + + + + + + + +`; + +exports[`Testing _controlledGate Controlled U gate with 1 control + 1 target 1`] = ` + + + + + + + + Foo + + + + +`; + +exports[`Testing _controlledGate Controlled U gate with 1 control + 1 target 2`] = ` + + + + + + + + Foo + + + + +`; + +exports[`Testing _controlledGate Controlled U gate with 1 control + 2 targets 1`] = ` + + + + + + + + Foo + + + + +`; + +exports[`Testing _controlledGate Controlled U gate with 1 control + 2 targets 2`] = ` + + + + + + + + Foo + + + + +`; + +exports[`Testing _controlledGate Controlled U gate with 1 control + 2 targets 3`] = ` + + + + + + + + Foo + + + + + + Foo + + + + +`; + +exports[`Testing _controlledGate Controlled U gate with 2 controls + 2 targets 1`] = ` + + + + + + + + + Foo + + + + +`; + +exports[`Testing _controlledGate Controlled U gate with 2 controls + 2 targets 2`] = ` + + + + + + + + + Foo + + + + +`; + +exports[`Testing _controlledGate Controlled U gate with 2 controls + 2 targets 3`] = ` + + + + + + + + + Foo + + + + + + Foo + + + + +`; + +exports[`Testing _controlledGate Controlled U gate with 2 controls + 2 targets 4`] = ` + + + + + + + + + Foo + + + + + + Foo + + + + +`; + +exports[`Testing _controlledGate Controlled U gate with multiple controls + 1 target 1`] = ` + + + + + + + + + Foo + + + + +`; + +exports[`Testing _controlledGate Controlled U gate with multiple controls + 1 target 2`] = ` + + + + + + + + + Foo + + + + +`; + +exports[`Testing _controlledGate Controlled U gate with multiple controls + 1 target 3`] = ` + + + + + + + + + Foo + + + + +`; + +exports[`Testing _controlledGate SWAP gate 1`] = ` + + + + + + + + + + + + +`; + +exports[`Testing _controlledGate SWAP gate 2`] = ` + + + + + + + + + + + + +`; + +exports[`Testing _controlledGate SWAP gate 3`] = ` + + + + + + + + + + + + +`; + +exports[`Testing _createGate Expanded gate 1`] = ` + + + + + + + +`; + +exports[`Testing _formatGate CNOT gate 1`] = ` + + + + + + + + + +`; + +exports[`Testing _formatGate classically controlled gate 1`] = ` + + + + + + + ? + + + + +`; + +exports[`Testing _formatGate controlled swap gate 1`] = ` + + + + + + + + + + + + +`; + +exports[`Testing _formatGate controlled unitary gate 1`] = ` + + + + + + + + U + + + + +`; + +exports[`Testing _formatGate controlled unitary gate with arguments 1`] = ` + + + + + + + + U + + + ('foo', 'bar') + + + + +`; + +exports[`Testing _formatGate gate with metadata 1`] = ` + + + + + + H + + + + +`; + +exports[`Testing _formatGate measure gate 1`] = ` + + + + + + + +`; + +exports[`Testing _formatGate multi-qubit unitary gate 1`] = ` + + + + + + U + + + + +`; + +exports[`Testing _formatGate multi-qubit unitary gate with arguments 1`] = ` + + + + + + + U + + + ('foo', 'bar') + + + + +`; + +exports[`Testing _formatGate single-qubit unitary gate 1`] = ` + + + + + + H + + + + +`; + +exports[`Testing _formatGate single-qubit unitary gate with arguments 1`] = ` + + + + + + Ry + + + (0.25) + + + + +`; + +exports[`Testing _formatGate swap gate 1`] = ` + + + + + + + + + + + + + + +`; + +exports[`Testing _groupedOperations children on consecutive registers 1`] = ` + + + + + + + + + X + + + + + + + + + + H + + + + + + +`; + +exports[`Testing _groupedOperations children on non-consecutive registers 1`] = ` + + + + + + + + + X + + + + + + + + + + H + + + + + + +`; + +exports[`Testing _groupedOperations children on same register 1`] = ` + + + + + + + + + X + + + + + + + + + + Z + + + + + + +`; + +exports[`Testing _groupedOperations multiple children 1`] = ` + + + + + + + + + X + + + + + + + + + + Z + + + + + + + + + + H + + + + + + +`; + +exports[`Testing _groupedOperations nested children 1`] = ` + + + + + + + + + + + + X + + + + + + + + + + Z + + + + + + + + + + + + H + + + + + + +`; + +exports[`Testing _groupedOperations one child 1`] = ` + + + + + + + + + X + + + + + + +`; + +exports[`Testing _measure 1 qubit + 1 classical registers 1`] = ` + + + + + +`; + +exports[`Testing _measure 2 qubit + 1 classical registers 1`] = ` + + + + + +`; + +exports[`Testing _measure 2 qubit + 2 classical registers 1`] = ` + + + + + +`; + +exports[`Testing _measure 2 qubit + 2 classical registers 2`] = ` + + + + + +`; + +exports[`Testing _swap Adjacent swap 1`] = ` + + + + + + + + + + + + +`; + +exports[`Testing _swap Adjacent swap 2`] = ` + + + + + + + + + + + + +`; + +exports[`Testing _swap Non-adjacent swap 1`] = ` + + + + + + + + + + + + +`; + +exports[`Testing _swap Non-adjacent swap 2`] = ` + + + + + + + + + + + + +`; + +exports[`Testing _unitary Multiqubit unitary on consecutive registers 1`] = ` + + + + + ZZ + + + +`; + +exports[`Testing _unitary Multiqubit unitary on consecutive registers 2`] = ` + + + + + ZZZ + + + +`; + +exports[`Testing _unitary Multiqubit unitary on non-consecutive registers 1`] = ` + + + + + + ZZ + + + + + + ZZ + + + +`; + +exports[`Testing _unitary Multiqubit unitary on non-consecutive registers 2`] = ` + + + + + + ZZZ + + + + + + ZZZ + + + +`; + +exports[`Testing _unitary Multiqubit unitary on non-consecutive registers 3`] = ` + + + + + ZZ + + + + + + ZZ + + + +`; + +exports[`Testing _unitary Multiqubit unitary on non-consecutive registers 4`] = ` + + + + + ZZZ + + + + + + ZZZ + + + +`; + +exports[`Testing _unitary Single qubit unitary 1`] = ` + + + + + H + + + +`; + +exports[`Testing _zoomButton Expanded gate 1`] = `null`; + +exports[`Testing _zoomButton Expanded with children gate 1`] = `null`; + +exports[`Testing _zoomButton Non-expanded with children gate 1`] = `null`; + +exports[`Testing _zoomButton Non-expanded with no children gate 1`] = `null`; + +exports[`Testing formatGates Multiple gates 1`] = ` + + + + + + + + + + + + + + + + + + X + + + + + + + + + + X + + + + + + + + + + + + +`; + +exports[`Testing formatGates Single gate 1`] = ` + + + + + + + + + + + +`; diff --git a/circuit_vis/__tests__/__snapshots__/inputFormatter.test.ts.snap b/circuit_vis/__tests__/__snapshots__/inputFormatter.test.ts.snap new file mode 100644 index 0000000000..fc1914accb --- /dev/null +++ b/circuit_vis/__tests__/__snapshots__/inputFormatter.test.ts.snap @@ -0,0 +1,170 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Testing _qubitInput classical register 1`] = ` + + |0⟩ + +`; + +exports[`Testing _qubitInput classical register 2`] = ` + + |0⟩ + +`; + +exports[`Testing _qubitInput classical register 3`] = ` + + |0⟩ + +`; + +exports[`Testing formatInputs 1 quantum register 1`] = ` + + + |0⟩ + + +`; + +exports[`Testing formatInputs Multiple quantum registers 1`] = ` + + + |0⟩ + + + |0⟩ + + + |0⟩ + + +`; + +exports[`Testing formatInputs Quantum and classical registers 1`] = ` + + + |0⟩ + + + |0⟩ + + + |0⟩ + + +`; + +exports[`Testing formatInputs Quantum and classical registers 2`] = ` + + + |0⟩ + + + |0⟩ + + + |0⟩ + + +`; + +exports[`Testing formatInputs Skip quantum registers 1`] = ` + + + |0⟩ + + + |0⟩ + + +`; diff --git a/circuit_vis/__tests__/__snapshots__/registerFormatter.test.ts.snap b/circuit_vis/__tests__/__snapshots__/registerFormatter.test.ts.snap new file mode 100644 index 0000000000..3487917ad4 --- /dev/null +++ b/circuit_vis/__tests__/__snapshots__/registerFormatter.test.ts.snap @@ -0,0 +1,1786 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Testing _classicalRegister register with label offset 1`] = ` + + + + + + +`; + +exports[`Testing _classicalRegister register with label offset 2`] = ` + + + + + + +`; + +exports[`Testing _classicalRegister register with label offset 3`] = ` + + + + + + +`; + +exports[`Testing _classicalRegister register with large width 1`] = ` + + + + + + +`; + +exports[`Testing _classicalRegister register with large width 2`] = ` + + + + + + +`; + +exports[`Testing _classicalRegister register with large width 3`] = ` + + + + + + +`; + +exports[`Testing _classicalRegister register with normal width 1`] = ` + + + + + + +`; + +exports[`Testing _classicalRegister register with normal width 2`] = ` + + + + + + +`; + +exports[`Testing _classicalRegister register with normal width 3`] = ` + + + + + + +`; + +exports[`Testing _classicalRegister register with small width 1`] = ` + + + + + + +`; + +exports[`Testing _classicalRegister register with small width 2`] = ` + + + + + + +`; + +exports[`Testing _classicalRegister register with small width 3`] = ` + + + + + + +`; + +exports[`Testing _qubitRegister register with label offset 1`] = ` + + + + q0 + + +`; + +exports[`Testing _qubitRegister register with label offset 2`] = ` + + + + q1 + + +`; + +exports[`Testing _qubitRegister register with label offset 3`] = ` + + + + q2 + + +`; + +exports[`Testing _qubitRegister register with large width 1`] = ` + + + + q0 + + +`; + +exports[`Testing _qubitRegister register with large width 2`] = ` + + + + q1 + + +`; + +exports[`Testing _qubitRegister register with large width 3`] = ` + + + + q2 + + +`; + +exports[`Testing _qubitRegister register with normal width 1`] = ` + + + + q0 + + +`; + +exports[`Testing _qubitRegister register with normal width 2`] = ` + + + + q1 + + +`; + +exports[`Testing _qubitRegister register with normal width 3`] = ` + + + + q2 + + +`; + +exports[`Testing _qubitRegister register with small width 1`] = ` + + + + q0 + + +`; + +exports[`Testing _qubitRegister register with small width 2`] = ` + + + + q1 + + +`; + +exports[`Testing _qubitRegister register with small width 3`] = ` + + + + q2 + + +`; + +exports[`Testing formatRegisters 1 quantum register 1`] = ` + + + + + q0 + + + +`; + +exports[`Testing formatRegisters 1 quantum register 2`] = ` + + + + + q0 + + + +`; + +exports[`Testing formatRegisters 1 quantum register 3`] = ` + + + + + q0 + + + +`; + +exports[`Testing formatRegisters Multiple quantum registers 1`] = ` + + + + + q0 + + + + + + q1 + + + + + + q2 + + + + + + q3 + + + +`; + +exports[`Testing formatRegisters Multiple quantum registers 2`] = ` + + + + + q0 + + + + + + q1 + + + + + + q2 + + + + + + q3 + + + +`; + +exports[`Testing formatRegisters Multiple quantum registers 3`] = ` + + + + + q0 + + + + + + q1 + + + + + + q2 + + + + + + q3 + + + +`; + +exports[`Testing formatRegisters Quantum and classical registers 1`] = ` + + + + + q0 + + + + + + q1 + + + + + + q2 + + + + + + + + + +`; + +exports[`Testing formatRegisters Quantum and classical registers 2`] = ` + + + + + q0 + + + + + + q1 + + + + + + q2 + + + + + + + + + +`; + +exports[`Testing formatRegisters Quantum and classical registers 3`] = ` + + + + + q0 + + + + + + q1 + + + + + + q2 + + + + + + + + + +`; + +exports[`Testing formatRegisters Quantum and classical registers 4`] = ` + + + + + q0 + + + + + + q1 + + + + + + q2 + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`Testing formatRegisters Quantum and classical registers 5`] = ` + + + + + q0 + + + + + + q1 + + + + + + q2 + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`Testing formatRegisters Quantum and classical registers 6`] = ` + + + + + q0 + + + + + + q1 + + + + + + q2 + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`Testing formatRegisters Skipped quantum registers 1`] = ` + + + + + q0 + + + + + + q2 + + + + + + q3 + + + +`; + +exports[`Testing formatRegisters Skipped quantum registers 2`] = ` + + + + + q0 + + + + + + q2 + + + + + + q3 + + + +`; + +exports[`Testing formatRegisters Skipped quantum registers 3`] = ` + + + + + q0 + + + + + + q2 + + + + + + q3 + + + +`; diff --git a/circuit_vis/__tests__/gateFormatter.test.ts b/circuit_vis/__tests__/gateFormatter.test.ts new file mode 100644 index 0000000000..ab277e3aa4 --- /dev/null +++ b/circuit_vis/__tests__/gateFormatter.test.ts @@ -0,0 +1,1010 @@ +import { + formatGates, + _formatGate, + _createGate, + _measure, + _unitary, + _swap, + _controlledGate, + _groupedOperations, + _classicalControlled, + _zoomButton, +} from '../src/formatters/gateFormatter'; +import { createSvgElement } from '../src/formatters/formatUtils'; +import { Metadata, GateType } from '../src/metadata'; +import { + startX, + startY, + registerHeight, + minGateWidth, + gatePadding, + classicalRegHeight, + controlBtnOffset, + groupBoxPadding, +} from '../src/constants'; + +describe('Testing _classicalControlled', () => { + test("one 'zero' child", () => { + const metadata: Metadata = { + type: GateType.ClassicalControlled, + x: startX, + controlsY: [startY + classicalRegHeight], + targetsY: [startY], + width: minGateWidth + controlBtnOffset + groupBoxPadding * 2, + label: '', + children: [ + [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, + label: 'X', + controlsY: [], + targetsY: [[startY]], + width: minGateWidth, + }, + ], + [], + ], + }; + expect(_classicalControlled(metadata)).toMatchSnapshot(); + }); + test("one 'one' child", () => { + const metadata: Metadata = { + type: GateType.ClassicalControlled, + x: startX, + controlsY: [startY + classicalRegHeight], + targetsY: [startY], + width: minGateWidth + controlBtnOffset + groupBoxPadding * 2, + label: '', + children: [ + [], + [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, + label: 'X', + controlsY: [], + targetsY: [[startY]], + width: minGateWidth, + }, + ], + ], + }; + expect(_classicalControlled(metadata)).toMatchSnapshot(); + }); + test("one 'zero'/'one' child", () => { + const metadata: Metadata = { + type: GateType.ClassicalControlled, + x: startX, + controlsY: [startY + classicalRegHeight], + targetsY: [startY, startY + classicalRegHeight * 2], + label: '', + width: minGateWidth + controlBtnOffset + groupBoxPadding * 2, + children: [ + [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, + controlsY: [], + targetsY: [[startY]], + label: 'X', + width: minGateWidth, + }, + ], + [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, + controlsY: [], + targetsY: [[startY + classicalRegHeight * 2]], + label: 'H', + width: minGateWidth, + }, + ], + ], + }; + expect(_classicalControlled(metadata)).toMatchSnapshot(); + }); + test("multiple 'zero'/'one' children", () => { + const metadata: Metadata = { + type: GateType.ClassicalControlled, + x: startX, + controlsY: [startY + classicalRegHeight], + targetsY: [startY, startY + classicalRegHeight * 2], + label: '', + width: minGateWidth * 2 + gatePadding * 2 + controlBtnOffset + groupBoxPadding * 2, + children: [ + [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, + controlsY: [], + targetsY: [[startY]], + label: 'X', + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: + startX + + minGateWidth + + minGateWidth / 2 + + gatePadding * 2 + + controlBtnOffset + + groupBoxPadding, + controlsY: [], + targetsY: [[startY]], + label: 'Z', + width: minGateWidth, + }, + ], + [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, + controlsY: [], + targetsY: [[startY + classicalRegHeight * 2]], + label: 'H', + width: minGateWidth, + }, + ], + ], + }; + expect(_classicalControlled(metadata)).toMatchSnapshot(); + }); + test('nested children', () => { + const metadata: Metadata = { + type: GateType.ClassicalControlled, + x: startX, + controlsY: [startY + registerHeight * 2], + targetsY: [startY, startY + registerHeight], + width: minGateWidth * 2 + gatePadding * 6, + label: 'if', + children: [ + [], + [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + gatePadding, + label: 'X', + controlsY: [], + targetsY: [[startY]], + width: minGateWidth, + }, + { + type: GateType.ClassicalControlled, + x: startX + minGateWidth + gatePadding * 3, + controlsY: [startY + registerHeight * 3], + targetsY: [startY, startY + registerHeight], + width: minGateWidth + gatePadding * 2, + label: 'if', + children: [ + [], + [ + { + type: GateType.Cnot, + x: startX + minGateWidth + gatePadding * 4 + minGateWidth / 2, + label: 'X', + controlsY: [startY + registerHeight], + targetsY: [startY], + width: minGateWidth, + }, + ], + ], + }, + ], + ], + }; + expect(_classicalControlled(metadata)).toMatchSnapshot(); + }); + test('No htmlClass', () => { + const metadata: Metadata = { + type: GateType.ClassicalControlled, + x: startX, + controlsY: [startY + registerHeight * 2], + targetsY: [startY, startY + registerHeight], + width: minGateWidth * 2 + gatePadding * 4, + label: 'if', + children: [ + [], + [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + gatePadding, + label: 'X', + controlsY: [], + targetsY: [[startY]], + width: minGateWidth, + }, + ], + ], + }; + expect(_classicalControlled(metadata)).toMatchSnapshot(); + }); + test('change padding', () => { + const metadata: Metadata = { + type: GateType.ClassicalControlled, + x: startX, + controlsY: [startY + registerHeight * 2], + targetsY: [startY, startY + registerHeight], + width: minGateWidth * 2 + gatePadding * 4, + label: 'if', + children: [ + [], + [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + gatePadding, + label: 'X', + controlsY: [], + targetsY: [[startY]], + width: minGateWidth, + }, + ], + ], + }; + expect(_classicalControlled(metadata, 20)).toMatchSnapshot(); + }); +}); + +describe('Testing _groupedOperations', () => { + test('one child', () => { + const metadata: Metadata = { + type: GateType.Group, + x: startX, + controlsY: [], + targetsY: [startY], + label: '', + width: minGateWidth + groupBoxPadding * 2, + children: [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + groupBoxPadding, + controlsY: [], + targetsY: [[startY]], + label: 'X', + width: minGateWidth, + }, + ], + }; + expect(_groupedOperations(metadata, 0)).toMatchSnapshot(); + }); + test('children on consecutive registers', () => { + const metadata: Metadata = { + type: GateType.Group, + x: startX, + controlsY: [], + targetsY: [startY, startY + registerHeight], + label: '', + width: minGateWidth + groupBoxPadding * 2, + children: [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + groupBoxPadding, + controlsY: [], + targetsY: [[startY]], + label: 'X', + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + groupBoxPadding, + controlsY: [], + targetsY: [[startY + registerHeight]], + label: 'H', + width: minGateWidth, + }, + ], + }; + expect(_groupedOperations(metadata, 0)).toMatchSnapshot(); + }); + test('children on non-consecutive registers', () => { + const metadata: Metadata = { + type: GateType.Group, + x: startX, + controlsY: [], + targetsY: [startY, startY + registerHeight * 2], + label: '', + width: minGateWidth + groupBoxPadding * 2, + children: [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + groupBoxPadding, + controlsY: [], + targetsY: [[startY]], + label: 'X', + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + groupBoxPadding, + controlsY: [], + targetsY: [[startY + registerHeight * 2]], + label: 'H', + width: minGateWidth, + }, + ], + }; + expect(_groupedOperations(metadata, 0)).toMatchSnapshot(); + }); + test('children on same register', () => { + const metadata: Metadata = { + type: GateType.Group, + x: startX, + controlsY: [], + targetsY: [startY], + label: '', + width: minGateWidth * 2 + gatePadding * 2 + groupBoxPadding * 2, + children: [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + groupBoxPadding, + controlsY: [], + targetsY: [[startY]], + label: 'X', + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + minGateWidth + minGateWidth / 2 + gatePadding * 2 + groupBoxPadding, + controlsY: [], + targetsY: [[startY]], + label: 'Z', + width: minGateWidth, + }, + ], + }; + expect(_groupedOperations(metadata, 0)).toMatchSnapshot(); + }); + test('multiple children', () => { + const metadata: Metadata = { + type: GateType.Group, + x: startX, + controlsY: [], + targetsY: [startY, startY + registerHeight], + label: '', + width: minGateWidth * 2 + gatePadding * 2 + groupBoxPadding * 2, + children: [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + groupBoxPadding, + controlsY: [], + targetsY: [[startY]], + label: 'X', + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + minGateWidth + minGateWidth / 2 + gatePadding * 2 + groupBoxPadding, + controlsY: [], + targetsY: [[startY]], + label: 'Z', + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + groupBoxPadding, + controlsY: [], + targetsY: [[startY + registerHeight]], + label: 'H', + width: minGateWidth, + }, + ], + }; + expect(_groupedOperations(metadata, 0)).toMatchSnapshot(); + }); + test('nested children', () => { + const metadata: Metadata = { + type: GateType.Group, + x: startX, + controlsY: [], + targetsY: [startY, startY + registerHeight], + label: '', + width: minGateWidth * 2 + gatePadding * 2 + groupBoxPadding * 4, + children: [ + { + type: GateType.Group, + x: startX + gatePadding, + controlsY: [], + targetsY: [startY], + label: '', + width: minGateWidth * 2 + gatePadding * 2 + groupBoxPadding * 2, + children: [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + groupBoxPadding * 2, + controlsY: [], + targetsY: [[startY]], + label: 'X', + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + minGateWidth + minGateWidth / 2 + gatePadding * 2 + groupBoxPadding * 2, + controlsY: [], + targetsY: [[startY]], + label: 'Z', + width: minGateWidth, + }, + ], + }, + { + type: GateType.Unitary, + x: startX + minGateWidth + gatePadding + groupBoxPadding * 2, + controlsY: [], + targetsY: [[startY + registerHeight]], + label: 'H', + width: minGateWidth, + }, + ], + }; + expect(_groupedOperations(metadata, 0)).toMatchSnapshot(); + }); +}); + +describe('Testing _controlledGate', () => { + test('CNOT gate', () => { + const metadata: Metadata = { + type: GateType.Cnot, + label: 'X', + x: startX, + controlsY: [startY], + targetsY: [startY + registerHeight], + width: minGateWidth, + }; + let svg: SVGElement = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); + + // Flip target and control + metadata.controlsY = [startY + registerHeight]; + metadata.targetsY = [startY]; + svg = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); + }); + test('SWAP gate', () => { + const metadata: Metadata = { + type: GateType.Swap, + label: '', + x: startX, + controlsY: [startY], + targetsY: [startY + registerHeight, startY + registerHeight * 2], + width: minGateWidth, + }; + // Control on top + let svg: SVGElement = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); + + // Control on bottom + metadata.controlsY = [startY + registerHeight * 2]; + metadata.targetsY = [startY, startY + registerHeight]; + svg = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); + + // Control in middle + metadata.controlsY = [startY + registerHeight]; + metadata.targetsY = [startY, startY + registerHeight * 2]; + svg = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); + }); + test('Controlled U gate with 1 control + 1 target', () => { + const metadata: Metadata = { + type: GateType.ControlledUnitary, + label: 'Foo', + x: startX, + controlsY: [startY], + targetsY: [[startY + registerHeight]], + width: 45, + }; + let svg: SVGElement = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); + + // Flip target and control + metadata.controlsY = [startY + registerHeight]; + metadata.targetsY = [[startY]]; + svg = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); + }); + test('Controlled U gate with multiple controls + 1 target', () => { + const metadata: Metadata = { + type: GateType.ControlledUnitary, + label: 'Foo', + x: startX, + controlsY: [startY, startY + registerHeight], + targetsY: [[startY + registerHeight * 2]], + width: 45, + }; + // Target on bottom + let svg: SVGElement = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); + + // Target on top + metadata.controlsY = [startY + registerHeight, startY + registerHeight * 2]; + metadata.targetsY = [[startY]]; + svg = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); + + // Target in middle + metadata.controlsY = [startY, startY + registerHeight * 2]; + metadata.targetsY = [[startY + registerHeight]]; + svg = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); + }); + test('Controlled U gate with 1 control + 2 targets', () => { + const metadata: Metadata = { + type: GateType.ControlledUnitary, + label: 'Foo', + x: startX, + controlsY: [startY + registerHeight * 2], + targetsY: [[startY, startY + registerHeight]], + width: 45, + }; + // Control on bottom + let svg: SVGElement = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); + + // Control on top + metadata.controlsY = [startY]; + metadata.targetsY = [[startY + registerHeight, startY + registerHeight * 2]]; + svg = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); + + // Control in middle + metadata.controlsY = [startY + registerHeight]; + metadata.targetsY = [[startY], [startY + registerHeight * 2]]; + svg = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); + }); + test('Controlled U gate with 2 controls + 2 targets', () => { + const metadata: Metadata = { + type: GateType.ControlledUnitary, + label: 'Foo', + x: startX, + controlsY: [startY + registerHeight * 2, startY + registerHeight * 3], + targetsY: [[startY, startY + registerHeight]], + width: 45, + }; + // Controls on bottom + let svg: SVGElement = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); + + // Controls on top + metadata.controlsY = [startY, startY + registerHeight]; + metadata.targetsY = [[startY + registerHeight * 2, startY + registerHeight * 3]]; + svg = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); + + // Controls in middle + metadata.controlsY = [startY + registerHeight, startY + registerHeight * 2]; + metadata.targetsY = [[startY], [startY + registerHeight * 3]]; + svg = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); + + // Interleaved controls/targets + metadata.controlsY = [startY + registerHeight, startY + registerHeight * 3]; + metadata.targetsY = [[startY], [startY + registerHeight * 2]]; + svg = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); + }); + test('Invalid gate', () => { + const metadata: Metadata = { + type: GateType.Measure, + label: 'X', + x: startX, + controlsY: [startY], + targetsY: [startY + registerHeight], + width: minGateWidth, + }; + expect(() => _controlledGate(metadata, 0)).toThrowError( + `ERROR: Unrecognized gate: X of type ${GateType.Measure}`, + ); + }); +}); + +describe('Testing _swap', () => { + const metadata: Metadata = { + type: GateType.Measure, + label: 'SWAP', + x: startX, + controlsY: [], + targetsY: [startY + registerHeight], + width: minGateWidth, + }; + + test('Adjacent swap', () => { + metadata.targetsY = [startY, startY + registerHeight]; + let svg: SVGElement = _swap(metadata, 0); + expect(svg).toMatchSnapshot(); + // Flip target and control + metadata.targetsY = [startY + registerHeight, startY]; + svg = _swap(metadata, 0); + expect(svg).toMatchSnapshot(); + }); + test('Non-adjacent swap', () => { + metadata.targetsY = [startY, startY + registerHeight * 2]; + let svg: SVGElement = _swap(metadata, 0); + expect(svg).toMatchSnapshot(); + // Flip target and control + metadata.targetsY = [startY + registerHeight * 2, startY]; + svg = _swap(metadata, 0); + expect(svg).toMatchSnapshot(); + }); +}); + +describe('Testing _unitary', () => { + test('Single qubit unitary', () => { + expect(_unitary('H', startX, [[startY]], minGateWidth)).toMatchSnapshot(); + }); + test('Multiqubit unitary on consecutive registers', () => { + let svg: SVGElement = _unitary('ZZ', startX, [[startY, startY + registerHeight]], minGateWidth); + expect(svg).toMatchSnapshot(); + svg = _unitary('ZZZ', startX, [[startY, startY + registerHeight, startY + registerHeight * 2]], minGateWidth); + expect(svg).toMatchSnapshot(); + }); + test('Multiqubit unitary on non-consecutive registers', () => { + // Dashed line between unitaries + let svg: SVGElement = _unitary('ZZ', startX, [[startY], [startY + registerHeight * 2]], minGateWidth); + expect(svg).toMatchSnapshot(); + svg = _unitary( + 'ZZZ', + startX, + [[startY], [startY + registerHeight * 2, startY + registerHeight * 3]], + minGateWidth, + ); + expect(svg).toMatchSnapshot(); + // Solid line + svg = _unitary('ZZ', startX, [[startY], [startY + registerHeight * 2]], minGateWidth, undefined, false); + expect(svg).toMatchSnapshot(); + svg = _unitary( + 'ZZZ', + startX, + [[startY], [startY + registerHeight * 2, startY + registerHeight * 3]], + minGateWidth, + undefined, + false, + ); + expect(svg).toMatchSnapshot(); + }); + test('No y coords', () => { + expect(() => _unitary('ZZ', startX, [], minGateWidth)).toThrowError( + 'Failed to render unitary gate (ZZ): has no y-values', + ); + }); +}); + +describe('Testing _measure', () => { + test('1 qubit + 1 classical registers', () => { + expect(_measure(startX, startY)).toMatchSnapshot(); + }); + test('2 qubit + 1 classical registers', () => { + expect(_measure(startX, startY)).toMatchSnapshot(); + }); + test('2 qubit + 2 classical registers', () => { + expect(_measure(startX, startY)).toMatchSnapshot(); + expect(_measure(startX, startY + registerHeight)).toMatchSnapshot(); + }); +}); + +describe('Testing _createGate', () => { + const metadata: Metadata = { + type: GateType.Invalid, + x: 0, + controlsY: [], + targetsY: [], + label: '', + width: -1, + dataAttributes: { a: '1', b: '2' }, + }; + const line: SVGElement = createSvgElement('line'); + test('Empty gate', () => { + expect(_createGate([line], metadata, 0).outerHTML).toEqual( + '', + ); + }); + test('Expanded gate', () => { + if (metadata.dataAttributes) metadata.dataAttributes['expanded'] = 'true'; + expect(_createGate([line], metadata, 0)).toMatchSnapshot(); + }); +}); + +describe('Testing _zoomButton', () => { + const metadata: Metadata = { + type: GateType.Group, + x: startX, + controlsY: [], + targetsY: [startY], + label: '', + width: minGateWidth + groupBoxPadding * 2, + children: [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + groupBoxPadding, + controlsY: [], + targetsY: [[startY]], + label: 'X', + width: minGateWidth, + }, + ], + }; + + test('Expanded gate', () => { + if (metadata.dataAttributes) { + metadata.dataAttributes['expanded'] = 'true'; + metadata.dataAttributes['zoom-in'] = 'true'; + } + expect(_zoomButton(metadata, 0)).toMatchSnapshot(); + }); + test('Non-expanded with no children gate', () => { + if (metadata.dataAttributes) { + delete metadata.dataAttributes['expanded']; + delete metadata.dataAttributes['zoom-in']; + } + expect(_zoomButton(metadata, 0)).toMatchSnapshot(); + }); + test('Non-expanded with children gate', () => { + if (metadata.dataAttributes) { + delete metadata.dataAttributes['expanded']; + metadata.dataAttributes['zoom-in'] = 'true'; + } + expect(_zoomButton(metadata, 0)).toMatchSnapshot(); + }); + test('Expanded with children gate', () => { + if (metadata.dataAttributes) { + metadata.dataAttributes['expanded'] = 'true'; + metadata.dataAttributes['zoom-in'] = 'true'; + } + expect(_zoomButton(metadata, 0)).toMatchSnapshot(); + }); +}); + +describe('Testing _formatGate', () => { + test('measure gate', () => { + const metadata: Metadata = { + type: GateType.Measure, + x: startX, + controlsY: [startY], + targetsY: [startY + registerHeight], + label: '', + width: minGateWidth, + }; + expect(_formatGate(metadata)).toMatchSnapshot(); + }); + test('single-qubit unitary gate', () => { + const metadata: Metadata = { + type: GateType.Unitary, + x: startX, + controlsY: [], + targetsY: [[startY]], + label: 'H', + width: minGateWidth, + }; + expect(_formatGate(metadata)).toMatchSnapshot(); + }); + test('single-qubit unitary gate with arguments', () => { + const metadata: Metadata = { + type: GateType.Unitary, + x: startX, + controlsY: [], + targetsY: [[startY]], + label: 'Ry', + displayArgs: '(0.25)', + width: 52, + }; + expect(_formatGate(metadata)).toMatchSnapshot(); + }); + test('multi-qubit unitary gate', () => { + const metadata: Metadata = { + type: GateType.Unitary, + x: startX, + controlsY: [], + targetsY: [[startY, startY + registerHeight]], + label: 'U', + width: minGateWidth, + }; + expect(_formatGate(metadata)).toMatchSnapshot(); + }); + test('multi-qubit unitary gate with arguments', () => { + const metadata: Metadata = { + type: GateType.ControlledUnitary, + x: startX, + controlsY: [], + targetsY: [[startY, startY + registerHeight]], + label: 'U', + displayArgs: "('foo', 'bar')", + width: 77, + }; + expect(_formatGate(metadata)).toMatchSnapshot(); + }); + test('swap gate', () => { + const metadata: Metadata = { + type: GateType.Swap, + x: startX, + controlsY: [], + targetsY: [startY, startY + registerHeight], + label: '', + width: minGateWidth, + }; + expect(_formatGate(metadata)).toMatchSnapshot(); + }); + test('controlled swap gate', () => { + const metadata: Metadata = { + type: GateType.Swap, + x: startX, + controlsY: [startY], + targetsY: [startY + registerHeight, startY + registerHeight * 2], + label: '', + width: minGateWidth, + }; + expect(_formatGate(metadata)).toMatchSnapshot(); + }); + test('CNOT gate', () => { + const metadata: Metadata = { + type: GateType.Cnot, + x: startX, + controlsY: [startY], + targetsY: [startY + registerHeight], + label: 'X', + width: minGateWidth, + }; + expect(_formatGate(metadata)).toMatchSnapshot(); + }); + test('controlled unitary gate', () => { + const metadata: Metadata = { + type: GateType.ControlledUnitary, + x: startX, + controlsY: [startY], + targetsY: [[startY + registerHeight]], + label: 'U', + width: minGateWidth, + }; + expect(_formatGate(metadata)).toMatchSnapshot(); + }); + test('controlled unitary gate with arguments', () => { + const metadata: Metadata = { + type: GateType.ControlledUnitary, + x: startX, + controlsY: [startY], + targetsY: [[startY + registerHeight]], + label: 'U', + displayArgs: "('foo', 'bar')", + width: 77, + }; + expect(_formatGate(metadata)).toMatchSnapshot(); + }); + test('classically controlled gate', () => { + const metadata: Metadata = { + type: GateType.ClassicalControlled, + x: startX, + controlsY: [startY + registerHeight * 2], + targetsY: [startY, startY + registerHeight], + label: '', + width: minGateWidth, + }; + expect(_formatGate(metadata)).toMatchSnapshot(); + }); + test('gate with metadata', () => { + const metadata: Metadata = { + type: GateType.Unitary, + x: startX, + controlsY: [], + targetsY: [[startY]], + label: 'H', + width: minGateWidth, + dataAttributes: { a: '1', b: '2' }, + }; + expect(_formatGate(metadata)).toMatchSnapshot(); + }); + test('invalid gate', () => { + const metadata: Metadata = { + type: GateType.Invalid, + x: startX, + controlsY: [startY], + targetsY: [startY + registerHeight], + label: 'Foo', + width: 48, + }; + expect(() => _formatGate(metadata)).toThrowError(`ERROR: unknown gate (Foo) of type ${GateType.Invalid}.`); + }); +}); + +describe('Testing formatGates', () => { + test('Single gate', () => { + const gates: Metadata[] = [ + { + type: GateType.Cnot, + x: startX, + controlsY: [startY], + targetsY: [startY + registerHeight], + label: 'X', + width: minGateWidth, + }, + ]; + expect(formatGates(gates)).toMatchSnapshot(); + }); + test('Single null gate', () => { + const gates: Metadata[] = [ + { + type: GateType.Invalid, + x: startX, + controlsY: [startY], + targetsY: [startY + registerHeight], + label: '', + width: minGateWidth, + }, + ]; + expect(() => formatGates(gates)).toThrowError(`ERROR: unknown gate () of type ${GateType.Invalid}.`); + }); + test('Multiple gates', () => { + const gates: Metadata[] = [ + { + type: GateType.Cnot, + x: startX, + controlsY: [startY + registerHeight], + targetsY: [startY], + label: 'X', + width: minGateWidth, + }, + { + type: GateType.ControlledUnitary, + x: startX, + controlsY: [startY + registerHeight], + targetsY: [[startY + registerHeight * 2]], + label: 'X', + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX, + controlsY: [], + targetsY: [[startY + registerHeight * 2]], + label: 'X', + width: minGateWidth, + }, + { + type: GateType.Measure, + x: startX, + controlsY: [startY], + targetsY: [startY + registerHeight * 3], + label: 'X', + width: minGateWidth, + }, + ]; + expect(formatGates(gates)).toMatchSnapshot(); + }); + test('Multiple gates with invalid gate', () => { + const gates: Metadata[] = [ + { + type: GateType.Unitary, + x: startX, + controlsY: [], + targetsY: [[startY + registerHeight * 2]], + label: 'X', + width: minGateWidth, + }, + { + type: GateType.Cnot, + x: startX, + controlsY: [startY + registerHeight], + targetsY: [startY], + label: 'X', + width: minGateWidth, + }, + { + type: GateType.Invalid, + x: startX, + controlsY: [], + targetsY: [startY + registerHeight * 2], + label: '', + width: minGateWidth, + }, + { + type: GateType.Invalid, + x: startX, + controlsY: [], + targetsY: [], + label: '', + width: minGateWidth, + }, + ]; + expect(() => formatGates(gates)).toThrowError(`ERROR: unknown gate () of type ${GateType.Invalid}.`); + }); +}); diff --git a/circuit_vis/__tests__/inputFormatter.test.ts b/circuit_vis/__tests__/inputFormatter.test.ts new file mode 100644 index 0000000000..62a04b52f0 --- /dev/null +++ b/circuit_vis/__tests__/inputFormatter.test.ts @@ -0,0 +1,84 @@ +import { Qubit } from '../src/circuit'; +import { RegisterMap, RegisterType } from '../src/register'; +import { formatInputs, _qubitInput } from '../src/formatters/inputFormatter'; +import { startY, registerHeight, classicalRegHeight } from '../src/constants'; + +describe('Testing _qubitInput', () => { + test('classical register', () => { + expect(_qubitInput(20)).toMatchSnapshot(); + expect(_qubitInput(50)).toMatchSnapshot(); + expect(_qubitInput(0)).toMatchSnapshot(); + }); +}); + +describe('Testing formatInputs', () => { + test('1 quantum register', () => { + const inputs: Qubit[] = [{ id: 0 }]; + const expectedRegs: RegisterMap = { 0: { type: RegisterType.Qubit, y: startY } }; + const { qubitWires, registers } = formatInputs(inputs); + expect(qubitWires).toMatchSnapshot(); + expect(registers).toEqual(expectedRegs); + expect(registers).toEqual(expectedRegs); + }); + test('Multiple quantum registers', () => { + const inputs: Qubit[] = [{ id: 0 }, { id: 1 }, { id: 2 }]; + const expectedRegs: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, + }; + const { qubitWires, registers } = formatInputs(inputs); + expect(qubitWires).toMatchSnapshot(); + expect(registers).toEqual(expectedRegs); + expect(registers).toEqual(expectedRegs); + }); + test('Quantum and classical registers', () => { + let inputs: Qubit[] = [{ id: 0, numChildren: 1 }, { id: 1 }, { id: 2 }]; + let expectedRegs: RegisterMap = { + 0: { + type: RegisterType.Qubit, + y: startY, + children: [{ type: RegisterType.Classical, y: startY + classicalRegHeight }], + }, + 1: { type: RegisterType.Qubit, y: startY + classicalRegHeight * 2 }, + 2: { type: RegisterType.Qubit, y: startY + registerHeight + classicalRegHeight * 2 }, + }; + let { qubitWires, registers } = formatInputs(inputs); + expect(qubitWires).toMatchSnapshot(); + expect(registers).toEqual(expectedRegs); + expect(registers).toEqual(expectedRegs); + + inputs = [{ id: 0 }, { id: 1, numChildren: 2 }, { id: 2, numChildren: 1 }]; + expectedRegs = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { + type: RegisterType.Qubit, + y: startY + registerHeight, + children: [ + { type: RegisterType.Classical, y: startY + registerHeight + classicalRegHeight }, + { type: RegisterType.Classical, y: startY + registerHeight + classicalRegHeight * 2 }, + ], + }, + 2: { + type: RegisterType.Qubit, + y: startY + registerHeight + classicalRegHeight * 3, + children: [{ type: RegisterType.Classical, y: startY + registerHeight + classicalRegHeight * 4 }], + }, + }; + ({ qubitWires, registers } = formatInputs(inputs)); + expect(qubitWires).toMatchSnapshot(); + expect(registers).toEqual(expectedRegs); + expect(registers).toEqual(expectedRegs); + }); + test('Skip quantum registers', () => { + const inputs: Qubit[] = [{ id: 0 }, { id: 2 }]; + const expectedRegs: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 2: { type: RegisterType.Qubit, y: startY + registerHeight }, + }; + const { qubitWires, registers } = formatInputs(inputs); + expect(qubitWires).toMatchSnapshot(); + expect(registers).toEqual(expectedRegs); + expect(registers).toEqual(expectedRegs); + }); +}); diff --git a/circuit_vis/__tests__/process.test.ts b/circuit_vis/__tests__/process.test.ts new file mode 100644 index 0000000000..5cd6b20c09 --- /dev/null +++ b/circuit_vis/__tests__/process.test.ts @@ -0,0 +1,2663 @@ +import { Operation, ConditionalRender } from '../src/circuit'; +import { RegisterMap, RegisterType, Register } from '../src/register'; +import { Metadata, GateType } from '../src/metadata'; +import { + processOperations, + _groupOperations, + _alignOps, + _getClassicalRegStart, + _opToMetadata, + _getRegY, + _splitTargetsY, + _fillMetadataX, + _offsetChildrenX, +} from '../src/process'; +import { + minGateWidth, + startX, + startY, + registerHeight, + gatePadding, + classicalRegHeight, + controlBtnOffset, + groupBoxPadding, +} from '../src/constants'; + +describe('Testing _groupOperations', () => { + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, + 3: { type: RegisterType.Qubit, y: startY + registerHeight * 3 }, + }; + test('single qubit gates on 1 qubit register', () => { + const operations: Operation[] = [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Y', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Z', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([[0, 1, 2], [], [], []]); + }); + test('single qubit gates on multiple qubit registers', () => { + const operations: Operation[] = [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Y', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: 'Z', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 2 }], + }, + { + gate: 'H', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'T', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([[0, 3], [1, 4], [2], []]); + }); + test('single and multiple qubit(s) gates', () => { + let operations: Operation[] = [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Y', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: 'Z', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([[0, 1, 2], [1], [], []]); + operations = [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Y', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Z', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([[0, 1, 2], [1], [], []]); + operations = [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Z', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Y', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([[0, 1, 2], [2], [], []]); + operations = [ + { + gate: 'Y', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Z', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([[0, 1, 2], [0], [], []]); + operations = [ + { + gate: 'Y', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Z', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([[0, 1], [0, 2], [], []]); + }); + test('multiple qubit gates in ladder format', () => { + const operations: Operation[] = [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Y', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 2 }], + }, + { + gate: 'Z', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 2 }], + targets: [{ type: RegisterType.Qubit, qId: 3 }], + }, + { + gate: 'H', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 2 }], + targets: [{ type: RegisterType.Qubit, qId: 3 }], + }, + { + gate: 'T', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 2 }], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([ + [0, 5], + [0, 1, 4, 5], + [1, 2, 3, 4], + [2, 3], + ]); + }); + test('multiple qubit gates in ladder format with single qubit gate', () => { + let operations: Operation[] = [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Y', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: 'Y', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 2 }], + }, + { + gate: 'Z', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 2 }], + targets: [{ type: RegisterType.Qubit, qId: 3 }], + }, + { + gate: 'Z', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 2 }], + }, + { + gate: 'H', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 2 }], + targets: [{ type: RegisterType.Qubit, qId: 3 }], + }, + { + gate: 'T', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 2 }], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: 'Y', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([ + [0, 8], + [0, 1, 2, 6, 7, 8], + [2, 3, 4, 5, 6], + [3, 5], + ]); + + operations = [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Y', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: 'Y', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 2 }], + }, + { + gate: 'Z', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 2 }], + }, + { + gate: 'T', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 2 }], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: 'Y', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: 'H', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'H', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'H', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'H', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([ + [0, 6, 7, 8, 9, 10], + [0, 1, 2, 4, 5, 10], + [2, 3, 4], + [], + ]); + }); + test('interleaved multiqubit gates', () => { + let operations: Operation[] = [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 3 }], + }, + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [{ type: RegisterType.Qubit, qId: 2 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([[1], [0, 1], [0, 1], [0]]); + operations = [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + ], + targets: [{ type: RegisterType.Qubit, qId: 3 }], + }, + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [ + { type: RegisterType.Qubit, qId: 2 }, + { type: RegisterType.Qubit, qId: 3 }, + ], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([ + [0, 1], + [0, 1], + [0, 1], + [0, 1], + ]); + operations = [ + { + gate: 'Foo', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 2 }, + { type: RegisterType.Qubit, qId: 3 }, + ], + }, + { + gate: 'Bar', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + { type: RegisterType.Qubit, qId: 2 }, + ], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([[0, 1], [0, 1], [0, 1], [0]]); + }); + test('classical control gates', () => { + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { + type: RegisterType.Qubit, + y: startY + registerHeight, + children: [{ type: RegisterType.Classical, y: startY + registerHeight + classicalRegHeight }], + }, + 2: { + type: RegisterType.Qubit, + y: startY + registerHeight + classicalRegHeight * 2, + children: [{ type: RegisterType.Classical, y: startY + registerHeight + classicalRegHeight * 3 }], + }, + 3: { type: RegisterType.Qubit, y: startY + registerHeight + classicalRegHeight * 4 }, + }; + let operations: Operation[] = [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Classical, qId: 2, cId: 0 }], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([[0, 1], [0], [0], [0]]); + operations = [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Classical, qId: 2, cId: 0 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([[0], [0, 1], [0], [0]]); + operations = [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Classical, qId: 1, cId: 0 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([[1], [0, 1], [1], [1]]); + }); + test('skipped registers', () => { + let operations: Operation[] = [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Z', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 2 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([[0], [], [1], []]); + operations = [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Z', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 2 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([[0], [0, 1], [1], []]); + }); + test('no qubits', () => { + const operations: Operation[] = [ + { + gate: 'NoOp1', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [], + }, + { + gate: 'NoOp2', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([[], [], [], []]); + }); + test('empty arguments', () => { + expect(_groupOperations([], {})).toEqual([]); + }); +}); + +describe('Testing _alignOps', () => { + test('single qubit gates', () => { + const ops: number[][] = [ + [0, 2, 5, 6], + [1, 3, 4], + ]; + expect(_alignOps(ops)).toEqual(ops); + }); + test('correct ordering of single qubit gate after multiqubit gate', () => { + const ops: number[][] = [ + [0, 1, 3], + [1, 2], + ]; + expect(_alignOps(ops)).toEqual([ + [0, 1, 3], + [null, 1, 2], + ]); + }); + test('padding of multiqubit register after single qubit gate', () => { + const ops: number[][] = [[1], [0, 1]]; + expect(_alignOps(ops)).toEqual([ + [null, 1], + [0, 1], + ]); + }); + test('no padding of single qubit gate after multiqubit gate on different registers', () => { + const ops: number[][] = [[0, 3], [2], [1, 2]]; + expect(_alignOps(ops)).toEqual([ + [0, 3], + [null, 2], + [1, 2], + ]); + }); + test('ladder of cnots', () => { + const ops: number[][] = [ + [0, 4], + [0, 1, 3, 4], + [1, 2, 3], + ]; + expect(_alignOps(ops)).toEqual([ + [0, null, null, null, 4], + [0, 1, null, 3, 4], + [null, 1, 2, 3], + ]); + }); + test('interleaved multiqubit gates', () => { + let ops: number[][] = [[0], [0, 1], [0, 1], [1]]; + expect(_alignOps(ops)).toEqual([[0], [0, 1], [0, 1], [null, 1]]); + ops = [[0], [0], [0, 1], [1], [1], [1]]; + expect(_alignOps(ops)).toEqual([[0], [0], [0, 1], [null, 1], [null, 1], [null, 1]]); + }); + test('skipped registers', () => { + let ops: number[][] = [[0], [], [1], []]; + expect(_alignOps(ops)).toEqual([[0], [], [1], []]); + ops = [[0], [], [1, 2], [2]]; + expect(_alignOps(ops)).toEqual([[0], [], [1, 2], [null, 2]]); + }); + test('no ops', () => { + expect(_alignOps([])).toEqual([]); + }); +}); + +describe('Testing _getClassicalRegStart', () => { + test('no measurement gates', () => { + const ops: Operation[] = [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Y', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ]; + const idxList: number[][] = [[0, 1]]; + expect(_getClassicalRegStart(ops, idxList)).toEqual([]); + }); + test('one measurement gate', () => { + const ops: Operation[] = [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'M', + isMeasurement: true, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], + }, + ]; + const idxList: number[][] = [[0, 1]]; + expect(_getClassicalRegStart(ops, idxList)).toEqual([[1, { type: RegisterType.Classical, qId: 0, cId: 0 }]]); + }); + test('multiple measurement gates', () => { + const ops: Operation[] = [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'M', + isMeasurement: true, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Classical, qId: 1, cId: 0 }], + }, + { + gate: 'M', + isMeasurement: true, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], + }, + { + gate: 'M', + isMeasurement: true, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], + }, + ]; + const idxList: number[][] = [[0, 2, 3], [1]]; + const clsRegs: [number, Register][] = [ + [1, { type: RegisterType.Classical, qId: 0, cId: 0 }], + [2, { type: RegisterType.Classical, qId: 0, cId: 0 }], + [0, { type: RegisterType.Classical, qId: 1, cId: 0 }], + ]; + expect(_getClassicalRegStart(ops, idxList)).toEqual(clsRegs); + }); +}); + +describe('Testing _opToMetadata', () => { + test('single qubit gate', () => { + const op: Operation = { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + }; + const metadata: Metadata = { + type: GateType.X, + x: 0, + controlsY: [], + targetsY: [startY + registerHeight], + label: 'X', + width: minGateWidth, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); + test('isAdjoint gate', () => { + const op: Operation = { + gate: 'Foo', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: true, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + }; + const metadata: Metadata = { + type: GateType.Unitary, + x: 0, + controlsY: [], + targetsY: [startY + registerHeight], + label: "Foo'", + width: 48, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); + test('measure gate', () => { + const op: Operation = { + gate: 'M', + isMeasurement: true, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], + }; + const registers: RegisterMap = { + 0: { + type: RegisterType.Qubit, + y: startY, + children: [{ type: RegisterType.Classical, y: startY + classicalRegHeight }], + }, + }; + const metadata: Metadata = { + type: GateType.Measure, + x: 0, + controlsY: [startY], + targetsY: [startY + classicalRegHeight], + label: '', + width: minGateWidth, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); + test('swap gate', () => { + const op: Operation = { + gate: 'SWAP', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + ], + }; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + }; + const metadata: Metadata = { + type: GateType.Swap, + x: 0, + controlsY: [], + targetsY: [startY, startY + registerHeight], + label: '', + width: minGateWidth, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); + test('isControlled swap gate', () => { + const op: Operation = { + gate: 'SWAP', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [ + { type: RegisterType.Qubit, qId: 1 }, + { type: RegisterType.Qubit, qId: 2 }, + ], + }; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, + }; + const metadata: Metadata = { + type: GateType.Swap, + x: 0, + controlsY: [startY], + targetsY: [startY + registerHeight, startY + registerHeight * 2], + label: '', + width: minGateWidth, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); + test('single qubit unitary gate', () => { + const op: Operation = { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + }; + const metadata: Metadata = { + type: GateType.X, + x: 0, + controlsY: [], + targetsY: [startY], + label: 'X', + width: minGateWidth, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); + test('multiqubit unitary gate', () => { + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, + }; + let op: Operation = { + gate: 'ZZ', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + ], + }; + let metadata: Metadata = { + type: GateType.Unitary, + x: 0, + controlsY: [], + targetsY: [startY, startY + registerHeight], + label: 'ZZ', + width: minGateWidth, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + op = { + gate: 'XX', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [ + { type: RegisterType.Qubit, qId: 1 }, + { type: RegisterType.Qubit, qId: 2 }, + ], + }; + metadata = { + type: GateType.Unitary, + x: 0, + controlsY: [], + targetsY: [startY + registerHeight, startY + registerHeight * 2], + label: 'XX', + width: minGateWidth, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); + test('isControlled unitary gates', () => { + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, + 3: { type: RegisterType.Qubit, y: startY + registerHeight * 3 }, + }; + let op: Operation = { + gate: 'ZZ', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }; + let metadata: Metadata = { + type: GateType.ControlledUnitary, + x: 0, + controlsY: [startY + registerHeight], + targetsY: [startY], + label: 'ZZ', + width: minGateWidth, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + op = { + gate: 'XX', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [ + { type: RegisterType.Qubit, qId: 1 }, + { type: RegisterType.Qubit, qId: 2 }, + ], + }; + metadata = { + type: GateType.ControlledUnitary, + x: 0, + controlsY: [startY], + targetsY: [startY + registerHeight, startY + registerHeight * 2], + label: 'XX', + width: minGateWidth, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + op = { + gate: 'Foo', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [ + { type: RegisterType.Qubit, qId: 2 }, + { type: RegisterType.Qubit, qId: 3 }, + ], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + ], + }; + metadata = { + type: GateType.ControlledUnitary, + label: 'Foo', + x: 0, + controlsY: [startY + registerHeight * 2, startY + registerHeight * 3], + targetsY: [startY, startY + registerHeight], + width: 45, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); + test('single-qubit unitary gates with arguments', () => { + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + }; + let op: Operation = { + gate: 'RX', + displayArgs: '(0.25)', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }; + let metadata: Metadata = { + type: GateType.Unitary, + x: 0, + controlsY: [], + targetsY: [startY], + label: 'RX', + displayArgs: '(0.25)', + width: 52, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + + // Test long argument + op = { + gate: 'RX', + displayArgs: "(0.25, 1.0, 'foobar', (3.14, 6.67))", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }; + metadata = { + type: GateType.Unitary, + x: 0, + controlsY: [], + targetsY: [startY], + label: 'RX', + displayArgs: "(0.25, 1.0, 'foobar', (3.14, 6.67))", + width: 188, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + + // Test isControlled + op = { + gate: 'RX', + displayArgs: '(0.25)', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }; + metadata = { + type: GateType.ControlledUnitary, + x: 0, + controlsY: [startY + registerHeight], + targetsY: [startY], + label: 'RX', + displayArgs: '(0.25)', + width: 52, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); + test('multi-qubit unitary gates with arguments', () => { + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, + }; + let op: Operation = { + gate: 'U', + displayArgs: "('foo', 'bar')", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + ], + }; + let metadata: Metadata = { + type: GateType.Unitary, + x: 0, + controlsY: [], + targetsY: [startY, startY + registerHeight], + label: 'U', + displayArgs: "('foo', 'bar')", + width: 77, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + + // Test long argument + op = { + gate: 'U', + displayArgs: "(0.25, 1.0, 'foobar', (3.14, 6.67))", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + ], + }; + metadata = { + type: GateType.Unitary, + x: 0, + controlsY: [], + targetsY: [startY, startY + registerHeight], + label: 'U', + displayArgs: "(0.25, 1.0, 'foobar', (3.14, 6.67))", + width: 188, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + + // Test isControlled + op = { + gate: 'U', + displayArgs: "('foo', 'bar')", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 2 }, + ], + }; + metadata = { + type: GateType.ControlledUnitary, + x: 0, + controlsY: [startY + registerHeight], + targetsY: [startY, startY + registerHeight * 2], + label: 'U', + displayArgs: "('foo', 'bar')", + width: 77, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); + test('classically-controlled gates', () => { + const op: Operation = { + gate: 'X', + isMeasurement: false, + isConditional: true, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + ], + children: [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + conditionalRender: ConditionalRender.OnZero, + }, + { + gate: 'H', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + conditionalRender: ConditionalRender.OnOne, + }, + ], + }; + const registers: RegisterMap = { + 0: { + type: RegisterType.Qubit, + y: startY, + children: [{ type: RegisterType.Classical, y: startY + classicalRegHeight }], + }, + 1: { type: RegisterType.Qubit, y: startY + classicalRegHeight * 2 }, + }; + const metadata: Metadata = { + type: GateType.ClassicalControlled, + x: 0, + controlsY: [startY + classicalRegHeight], + targetsY: [startY, startY + classicalRegHeight * 2], + label: '', + width: minGateWidth + controlBtnOffset + groupBoxPadding * 2, + children: [ + [ + { + type: GateType.X, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [startY], + label: 'X', + width: minGateWidth, + }, + ], + [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [[startY + classicalRegHeight * 2]], + label: 'H', + width: minGateWidth, + }, + ], + ], + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); + test('grouped gates', () => { + const op: Operation = { + gate: 'Foo', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + conditionalRender: ConditionalRender.AsGroup, + controls: [], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + ], + children: [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + conditionalRender: ConditionalRender.OnZero, + }, + { + gate: 'H', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + conditionalRender: ConditionalRender.OnOne, + }, + ], + }; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + }; + const metadata: Metadata = { + type: GateType.Group, + x: 0, + controlsY: [], + targetsY: [startY, startY + registerHeight], + label: '', + width: minGateWidth + groupBoxPadding * 2, + dataAttributes: { expanded: 'true' }, + children: [ + { + type: GateType.X, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [startY], + label: 'X', + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [[startY + registerHeight]], + label: 'H', + width: minGateWidth, + }, + ], + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); + test('no render on null', () => { + const metadata: Metadata = { + type: GateType.Invalid, + x: 0, + controlsY: [], + targetsY: [], + label: '', + width: -1, + }; + expect(_opToMetadata(null, [])).toEqual(metadata); + }); + test('Invalid register', () => { + let op: Operation = { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + }; + expect(() => _opToMetadata(op, registers)).toThrowError('ERROR: Qubit register with ID 1 not found.'); + + op = { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [{ type: RegisterType.Classical, qId: 0, cId: 2 }], + targets: [], + }; + expect(() => _opToMetadata(op, registers)).toThrowError('ERROR: No classical registers found for qubit ID 0.'); + }); + test('skipped registers', () => { + const op: Operation = { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 2 }], + }; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 2: { type: RegisterType.Qubit, y: startY + registerHeight }, + }; + const metadata: Metadata = { + type: GateType.X, + x: 0, + controlsY: [], + targetsY: [startY + registerHeight], + label: 'X', + width: minGateWidth, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); +}); + +describe('Testing _getRegY', () => { + const registers: RegisterMap = { + 0: { + type: RegisterType.Qubit, + y: startY, + children: [{ type: RegisterType.Classical, y: startY + classicalRegHeight }], + }, + }; + test('quantum register', () => { + const reg: Register = { type: RegisterType.Qubit, qId: 0 }; + expect(_getRegY(reg, registers)).toEqual(startY); + }); + test('classical register', () => { + const reg: Register = { type: RegisterType.Classical, qId: 0, cId: 0 }; + expect(_getRegY(reg, registers)).toEqual(startY + classicalRegHeight); + }); + test('No children', () => { + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + }; + const reg: Register = { type: RegisterType.Classical, qId: 0, cId: 0 }; + expect(() => _getRegY(reg, registers)).toThrowError('ERROR: No classical registers found for qubit ID 0.'); + }); + test('Null cId', () => { + const reg: Register = { type: RegisterType.Classical, qId: 0 }; + expect(() => _getRegY(reg, registers)).toThrowError( + 'ERROR: No ID defined for classical register associated with qubit ID 0.', + ); + }); + test('Invalid cId', () => { + const reg: Register = { type: RegisterType.Classical, qId: 0, cId: 1 }; + expect(() => _getRegY(reg, registers)).toThrowError( + 'ERROR: Classical register ID 1 invalid for qubit ID 0 with 1 classical register(s).', + ); + }); + test('Invalid register type', () => { + const reg: Register = { type: 2, qId: 0, cId: 1 }; + expect(() => _getRegY(reg, registers)).toThrowError('ERROR: Unknown register type 2.'); + }); +}); + +describe('Testing _splitTargetsY', () => { + const registers: RegisterMap = { + 0: { + type: RegisterType.Qubit, + y: startY, + }, + 1: { + type: RegisterType.Qubit, + y: startY + registerHeight, + children: [{ type: RegisterType.Classical, y: startY + registerHeight + classicalRegHeight }], + }, + 2: { + type: RegisterType.Qubit, + y: startY + registerHeight * 2 + classicalRegHeight, + children: [ + { type: RegisterType.Classical, y: startY + registerHeight * 2 + classicalRegHeight * 2 }, + { type: RegisterType.Classical, y: startY + registerHeight * 2 + classicalRegHeight * 3 }, + { type: RegisterType.Classical, y: startY + registerHeight * 2 + classicalRegHeight * 4 }, + ], + }, + }; + test('adjacent qubit regs', () => { + const targets: Register[] = [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 2 }, + { type: RegisterType.Qubit, qId: 1 }, + ]; + const targetsY: number[] = [startY, startY + registerHeight, startY + registerHeight * 2 + classicalRegHeight]; + expect(_splitTargetsY(targets, [], registers)).toEqual([targetsY]); + expect(_splitTargetsY(targets, [0], registers)).toEqual([targetsY]); + expect(_splitTargetsY(targets, [startY + registerHeight * 3], registers)).toEqual([targetsY]); + expect(_splitTargetsY(targets, [0, startY + registerHeight * 3], registers)).toEqual([targetsY]); + }); + test('adjacent classical regs', () => { + const targets: Register[] = [ + { type: RegisterType.Classical, qId: 2, cId: 0 }, + { type: RegisterType.Classical, qId: 2, cId: 2 }, + { type: RegisterType.Classical, qId: 2, cId: 1 }, + ]; + const targetsY: number[] = [ + startY + registerHeight * 2 + classicalRegHeight * 2, + startY + registerHeight * 2 + classicalRegHeight * 3, + startY + registerHeight * 2 + classicalRegHeight * 4, + ]; + expect(_splitTargetsY(targets, [], registers)).toEqual([targetsY]); + expect(_splitTargetsY(targets, [0], registers)).toEqual([targetsY]); + expect(_splitTargetsY(targets, [startY + registerHeight * 3 + classicalRegHeight * 4], registers)).toEqual([ + targetsY, + ]); + expect(_splitTargetsY(targets, [0, startY + registerHeight * 3 + classicalRegHeight * 4], registers)).toEqual([ + targetsY, + ]); + }); + test('adjacent qubit/classical regs', () => { + const targets: Register[] = [ + { type: RegisterType.Qubit, qId: 2 }, + { type: RegisterType.Classical, qId: 1, cId: 0 }, + { type: RegisterType.Classical, qId: 2, cId: 0 }, + ]; + const targetsY: number[] = [ + startY + registerHeight + classicalRegHeight, + startY + registerHeight * 2 + classicalRegHeight, + startY + registerHeight * 2 + classicalRegHeight * 2, + ]; + expect(_splitTargetsY(targets, [], registers)).toEqual([targetsY]); + expect(_splitTargetsY(targets, [0], registers)).toEqual([targetsY]); + expect(_splitTargetsY(targets, [startY + registerHeight * 3 + classicalRegHeight * 4], registers)).toEqual([ + targetsY, + ]); + expect(_splitTargetsY(targets, [0, startY + registerHeight * 3 + classicalRegHeight * 4], registers)).toEqual([ + targetsY, + ]); + }); + test('single target', () => { + const targets: Register[] = [{ type: RegisterType.Qubit, qId: 0 }]; + expect(_splitTargetsY(targets, [], registers)).toEqual([[startY]]); + expect(_splitTargetsY(targets, [0], registers)).toEqual([[startY]]); + expect(_splitTargetsY(targets, [startY + registerHeight], registers)).toEqual([[startY]]); + expect(_splitTargetsY(targets, [0, startY + registerHeight], registers)).toEqual([[startY]]); + }); + test('split non-adjacent qubit regs', () => { + const targets: Register[] = [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 2 }, + ]; + const targetsY: number[][] = [[startY], [startY + registerHeight * 2 + classicalRegHeight]]; + expect(_splitTargetsY(targets, [], registers)).toEqual(targetsY); + expect(_splitTargetsY(targets, [0], registers)).toEqual(targetsY); + expect(_splitTargetsY(targets, [startY + registerHeight * 3], registers)).toEqual(targetsY); + expect(_splitTargetsY(targets, [0, startY + registerHeight * 3], registers)).toEqual(targetsY); + }); + test('split two qubit regs with classical register', () => { + const targets: Register[] = [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + ]; + const targetsY: number[][] = [[startY], [startY + registerHeight]]; + expect(_splitTargetsY(targets, [startY + classicalRegHeight], registers)).toEqual(targetsY); + expect(_splitTargetsY(targets, [0, startY + classicalRegHeight], registers)).toEqual(targetsY); + expect(_splitTargetsY(targets, [startY + registerHeight * 2, startY + classicalRegHeight], registers)).toEqual( + targetsY, + ); + expect( + _splitTargetsY(targets, [startY + registerHeight * 2, 0, startY + classicalRegHeight], registers), + ).toEqual(targetsY); + }); + test('split two classical regs with classical reg', () => { + const targets: Register[] = [ + { type: RegisterType.Classical, qId: 2, cId: 0 }, + { type: RegisterType.Classical, qId: 2, cId: 2 }, + ]; + const targetsY: number[][] = [ + [startY + registerHeight * 2 + classicalRegHeight * 2], + [startY + registerHeight * 2 + classicalRegHeight * 4], + ]; + expect(_splitTargetsY(targets, [startY + registerHeight * 2 + classicalRegHeight * 3], registers)).toEqual( + targetsY, + ); + expect(_splitTargetsY(targets, [0, startY + registerHeight * 2 + classicalRegHeight * 3], registers)).toEqual( + targetsY, + ); + expect( + _splitTargetsY( + targets, + [ + startY + registerHeight * 3 + classicalRegHeight * 2, + startY + registerHeight * 2 + classicalRegHeight * 3, + ], + registers, + ), + ).toEqual(targetsY); + expect( + _splitTargetsY( + targets, + [ + startY + registerHeight * 3 + classicalRegHeight * 2, + 0, + startY + registerHeight * 2 + classicalRegHeight * 3, + ], + registers, + ), + ).toEqual(targetsY); + }); + test('split multiple targets with classical register', () => { + const targets: Register[] = [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 2 }, + { type: RegisterType.Qubit, qId: 1 }, + ]; + let targetsY: number[][] = [ + [startY], + [startY + registerHeight, startY + registerHeight * 2 + classicalRegHeight], + ]; + expect(_splitTargetsY(targets, [startY + classicalRegHeight], registers)).toEqual(targetsY); + expect(_splitTargetsY(targets, [10, startY + classicalRegHeight], registers)).toEqual(targetsY); + expect(_splitTargetsY(targets, [60, startY + classicalRegHeight], registers)).toEqual(targetsY); + + targetsY = [[startY, startY + registerHeight], [startY + registerHeight * 2 + classicalRegHeight]]; + expect(_splitTargetsY(targets, [startY + registerHeight + classicalRegHeight], registers)).toEqual(targetsY); + }); +}); + +describe('Testing _offsetChildrenX', () => { + const offset = 50; + test('no grandchildren', () => { + const children: Metadata[][] = [ + [ + { + type: GateType.X, + x: 0, + controlsY: [], + targetsY: [], + width: minGateWidth, + label: 'X', + }, + ], + ]; + const expected: Metadata[][] = [ + [ + { + type: GateType.X, + x: 50, + controlsY: [], + targetsY: [], + width: minGateWidth, + label: 'X', + }, + ], + ]; + _offsetChildrenX(children, offset); + expect(children).toEqual(expected); + }); + test('has grandchildren', () => { + const children: Metadata[][] = [ + [ + { + type: GateType.X, + x: 0, + controlsY: [], + targetsY: [], + width: minGateWidth, + label: 'X', + children: [ + [ + { + type: GateType.X, + x: 0, + controlsY: [], + targetsY: [], + width: minGateWidth, + label: 'X', + }, + ], + [], + ], + }, + ], + ]; + const expected: Metadata[][] = [ + [ + { + type: GateType.X, + x: 50, + controlsY: [], + targetsY: [], + width: minGateWidth, + label: 'X', + children: [ + [ + { + type: GateType.X, + x: 50, + controlsY: [], + targetsY: [], + width: minGateWidth, + label: 'X', + }, + ], + [], + ], + }, + ], + ]; + _offsetChildrenX(children, offset); + expect(children).toEqual(expected); + }); + test('undefined child', () => { + expect(() => _offsetChildrenX(undefined, offset)).not.toThrow(); + }); +}); + +describe('Testing _fillMetadataX', () => { + test('Non-classically-isControlled gate', () => { + const columnWidths: number[] = Array(1).fill(minGateWidth); + const expectedEndX = startX + minGateWidth + gatePadding * 2; + const opsMetadata: Metadata[][] = [ + [ + { + type: GateType.X, + x: 0, + controlsY: [], + targetsY: [], + label: 'X', + width: minGateWidth, + }, + ], + ]; + const expected: Metadata[][] = [ + [ + { + type: GateType.X, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [], + label: 'X', + width: minGateWidth, + }, + ], + ]; + const endX: number = _fillMetadataX(opsMetadata, columnWidths); + expect(opsMetadata).toEqual(expected); + expect(endX).toEqual(expectedEndX); + }); + test('classically-isControlled gate with no children', () => { + const columnWidths: number[] = Array(1).fill(minGateWidth); + const expectedEndX = startX + minGateWidth + gatePadding * 2; + const opsMetadata: Metadata[][] = [ + [ + { + type: GateType.ClassicalControlled, + x: 0, + controlsY: [], + targetsY: [], + label: 'X', + width: minGateWidth, + }, + ], + ]; + const expected: Metadata[][] = [ + [ + { + type: GateType.ClassicalControlled, + x: startX, + controlsY: [], + targetsY: [], + label: 'X', + width: minGateWidth, + }, + ], + ]; + const endX: number = _fillMetadataX(opsMetadata, columnWidths); + expect(opsMetadata).toEqual(expected); + expect(endX).toEqual(expectedEndX); + }); + test('depth-1 children', () => { + const columnWidths: number[] = Array(1).fill(minGateWidth + gatePadding * 2); + const expectedEndX = startX + minGateWidth + gatePadding * 4; + const opsMetadata: Metadata[][] = [ + [ + { + type: GateType.ClassicalControlled, + x: 0, + controlsY: [], + targetsY: [], + children: [ + [ + { + type: GateType.X, + x: 0, + controlsY: [], + targetsY: [], + label: 'X', + width: minGateWidth, + }, + ], + [ + { + type: GateType.X, + x: 0, + controlsY: [], + targetsY: [], + label: 'X', + width: minGateWidth, + }, + ], + ], + label: 'X', + width: minGateWidth + controlBtnOffset + groupBoxPadding * 2, + }, + ], + ]; + const expected: Metadata[][] = [ + [ + { + type: GateType.ClassicalControlled, + x: startX, + controlsY: [], + targetsY: [], + children: [ + [ + { + type: GateType.X, + x: controlBtnOffset + groupBoxPadding, + controlsY: [], + targetsY: [], + label: 'X', + width: minGateWidth, + }, + ], + [ + { + type: GateType.X, + x: controlBtnOffset + groupBoxPadding, + controlsY: [], + targetsY: [], + label: 'X', + width: minGateWidth, + }, + ], + ], + label: 'X', + width: minGateWidth + controlBtnOffset + groupBoxPadding * 2, + }, + ], + ]; + + const endX: number = _fillMetadataX(opsMetadata, columnWidths); + expect(opsMetadata).toEqual(expected); + expect(endX).toEqual(expectedEndX); + }); + test('empty args', () => { + const opsMetadata: Metadata[][] = []; + const endX: number = _fillMetadataX(opsMetadata, []); + expect(opsMetadata).toEqual([]); + expect(endX).toEqual(startX); + }); +}); + +describe('Testing processOperations', () => { + test('single qubit gates', () => { + const rxWidth = 52; + const operations: Operation[] = [ + { + gate: 'H', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ qId: 0 }], + }, + { + gate: 'H', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ qId: 0 }], + }, + { + gate: 'H', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ qId: 1 }], + }, + { + gate: 'RX', + displayArgs: '(0.25)', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ qId: 1 }], + }, + ]; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + }; + const expectedOps: Metadata[] = [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [[startY]], + label: 'H', + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + (minGateWidth + gatePadding * 2) + rxWidth / 2, + controlsY: [], + targetsY: [[startY]], + label: 'H', + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [[startY + registerHeight]], + label: 'H', + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + (minGateWidth + gatePadding * 2) + rxWidth / 2, + controlsY: [], + targetsY: [[startY + registerHeight]], + label: 'RX', + displayArgs: '(0.25)', + width: rxWidth, + }, + ]; + const expectedWidth: number = startX + minGateWidth + rxWidth + gatePadding * 4; + const { metadataList, svgWidth } = processOperations(operations, registers); + expect(metadataList).toEqual(expectedOps); + expect(svgWidth).toEqual(expectedWidth); + }); + test('single wide qubit gates', () => { + const expectedCustomWidth = 67; + const operations: Operation[] = [ + { + gate: 'H', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'FooBar', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'H', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + ]; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + }; + const expectedOps: Metadata[] = [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [[startY]], + label: 'H', + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + (minGateWidth + gatePadding * 2) + expectedCustomWidth / 2, + controlsY: [], + targetsY: [[startY]], + label: 'FooBar', + width: expectedCustomWidth, + }, + { + type: GateType.Unitary, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [[startY + registerHeight]], + label: 'H', + width: minGateWidth, + }, + ]; + const expectedWidth: number = startX + minGateWidth + expectedCustomWidth + gatePadding * 4; + const { metadataList, svgWidth } = processOperations(operations, registers); + expect(metadataList).toEqual(expectedOps); + expect(svgWidth).toEqual(expectedWidth); + }); + test('single and multi qubit gates', () => { + const operations: Operation[] = [ + { + gate: 'H', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'H', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + ]; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + }; + const expectedOps: Metadata[] = [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [[startY]], + label: 'H', + width: minGateWidth, + }, + { + type: GateType.Cnot, + x: startX + (minGateWidth + gatePadding * 2) + minGateWidth / 2, + controlsY: [startY + registerHeight], + targetsY: [startY], + label: 'X', + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + (minGateWidth + gatePadding * 2) * 2 + minGateWidth / 2, + controlsY: [], + targetsY: [[startY + registerHeight]], + label: 'H', + width: minGateWidth, + }, + ]; + const expectedWidth: number = startX + (minGateWidth + gatePadding * 2) * 3; + const { metadataList, svgWidth } = processOperations(operations, registers); + expect(metadataList).toEqual(expectedOps); + expect(svgWidth).toEqual(expectedWidth); + }); + test('classically-controlled gates', () => { + const op: Operation = { + gate: 'X', + isMeasurement: false, + isConditional: true, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + ], + children: [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + conditionalRender: ConditionalRender.OnZero, + }, + { + gate: 'H', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + conditionalRender: ConditionalRender.OnOne, + }, + { + gate: 'Z', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + conditionalRender: ConditionalRender.OnZero, + }, + ], + }; + const registers: RegisterMap = { + 0: { + type: RegisterType.Qubit, + y: startY, + children: [{ type: RegisterType.Classical, y: startY + classicalRegHeight }], + }, + 1: { type: RegisterType.Qubit, y: startY + classicalRegHeight * 2 }, + }; + const metadata: Metadata = { + type: GateType.ClassicalControlled, + x: startX, + controlsY: [startY + classicalRegHeight], + targetsY: [startY, startY + classicalRegHeight * 2], + label: '', + width: minGateWidth * 2 + gatePadding * 2 + controlBtnOffset + groupBoxPadding * 2, + children: [ + [ + { + type: GateType.X, + x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, + controlsY: [], + targetsY: [startY], + label: 'X', + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: + startX + + minGateWidth + + minGateWidth / 2 + + gatePadding * 2 + + controlBtnOffset + + groupBoxPadding, + controlsY: [], + targetsY: [[startY]], + label: 'Z', + width: minGateWidth, + }, + ], + [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, + controlsY: [], + targetsY: [[startY + classicalRegHeight * 2]], + label: 'H', + width: minGateWidth, + }, + ], + ], + }; + const expectedWidth: number = + startX + minGateWidth * 2 + gatePadding * 4 + controlBtnOffset + groupBoxPadding * 2; + const { metadataList, svgWidth } = processOperations([op], registers); + expect(metadataList).toEqual([metadata]); + expect(svgWidth).toEqual(expectedWidth); + }); + test('grouped gates', () => { + const op: Operation = { + gate: 'Foo', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + ], + conditionalRender: ConditionalRender.AsGroup, + children: [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'H', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: 'Z', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ], + }; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + }; + const metadata: Metadata = { + type: GateType.Group, + x: startX, + controlsY: [], + targetsY: [startY, startY + registerHeight], + label: '', + width: minGateWidth * 2 + gatePadding * 2 + groupBoxPadding * 2, + dataAttributes: { expanded: 'true' }, + children: [ + { + type: GateType.X, + x: startX + minGateWidth / 2 + groupBoxPadding, + controlsY: [], + targetsY: [startY], + label: 'X', + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + minGateWidth + minGateWidth / 2 + gatePadding * 2 + groupBoxPadding, + controlsY: [], + targetsY: [[startY]], + label: 'Z', + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + groupBoxPadding, + controlsY: [], + targetsY: [[startY + registerHeight]], + label: 'H', + width: minGateWidth, + }, + ], + }; + const expectedWidth: number = startX + minGateWidth * 2 + gatePadding * 4 + groupBoxPadding * 2; + const { metadataList, svgWidth } = processOperations([op], registers); + expect(metadataList).toEqual([metadata]); + expect(svgWidth).toEqual(expectedWidth); + }); + test('nested grouped gates', () => { + const op: Operation = { + gate: 'Foo', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + ], + conditionalRender: ConditionalRender.AsGroup, + children: [ + { + gate: 'Foo', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + conditionalRender: ConditionalRender.AsGroup, + children: [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Z', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ], + }, + { + gate: 'H', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + ], + }; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + }; + const metadata: Metadata = { + type: GateType.Group, + x: startX, + controlsY: [], + targetsY: [startY, startY + registerHeight], + label: '', + width: minGateWidth * 2 + gatePadding * 2 + groupBoxPadding * 4, + dataAttributes: { expanded: 'true' }, + children: [ + { + type: GateType.Group, + x: startX + gatePadding, + controlsY: [], + targetsY: [startY], + label: '', + width: minGateWidth * 2 + gatePadding * 2 + groupBoxPadding * 2, + dataAttributes: { expanded: 'true' }, + children: [ + { + type: GateType.X, + x: startX + minGateWidth / 2 + groupBoxPadding * 2, + controlsY: [], + targetsY: [startY], + label: 'X', + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + minGateWidth + minGateWidth / 2 + gatePadding * 2 + groupBoxPadding * 2, + controlsY: [], + targetsY: [[startY]], + label: 'Z', + width: minGateWidth, + }, + ], + }, + { + type: GateType.Unitary, + x: startX + minGateWidth + gatePadding + groupBoxPadding * 2, // startX + half of above gate's width + padding + controlsY: [], + targetsY: [[startY + registerHeight]], + label: 'H', + width: minGateWidth, + }, + ], + }; + const expectedWidth: number = startX + minGateWidth * 2 + gatePadding * 4 + groupBoxPadding * 4; + const { metadataList, svgWidth } = processOperations([op], registers); + expect(metadataList).toEqual([metadata]); + expect(svgWidth).toEqual(expectedWidth); + }); + test('measure gates', () => { + const operations: Operation[] = [ + { + gate: 'H', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'M', + isMeasurement: true, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], + }, + { + gate: 'H', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: 'M', + isMeasurement: true, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [{ type: RegisterType.Classical, qId: 0, cId: 1 }], + }, + ]; + const registers: RegisterMap = { + 0: { + type: RegisterType.Qubit, + y: startY, + children: [ + { type: RegisterType.Classical, y: startY + classicalRegHeight }, + { type: RegisterType.Classical, y: startY + classicalRegHeight * 2 }, + ], + }, + 1: { type: RegisterType.Qubit, y: startY + classicalRegHeight * 3 }, + }; + const expectedOps: Metadata[] = [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [[startY]], + label: 'H', + width: minGateWidth, + }, + { + type: GateType.Measure, + x: startX + minGateWidth + gatePadding * 2 + minGateWidth / 2, + controlsY: [startY], + targetsY: [startY + classicalRegHeight], + label: '', + width: minGateWidth, + }, + { + type: GateType.Measure, + x: startX + (minGateWidth + gatePadding * 2) * 2 + minGateWidth / 2, + controlsY: [startY], + targetsY: [startY + classicalRegHeight * 2], + label: '', + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [[startY + classicalRegHeight * 3]], + label: 'H', + width: minGateWidth, + }, + ]; + const expectedWidth: number = startX + (minGateWidth + gatePadding * 2) * 3; + const { metadataList, svgWidth } = processOperations(operations, registers); + expect(metadataList).toEqual(expectedOps); + expect(svgWidth).toEqual(expectedWidth); + }); + test('skipped registers', () => { + const operations: Operation[] = [ + { + gate: 'H', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'H', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 2 }], + }, + ]; + const registers: RegisterMap = { + 0: { + type: RegisterType.Qubit, + y: startY, + children: [ + { type: RegisterType.Classical, y: startY + classicalRegHeight }, + { type: RegisterType.Classical, y: startY + classicalRegHeight * 2 }, + ], + }, + 2: { type: RegisterType.Qubit, y: startY + classicalRegHeight * 3 }, + }; + const expectedOps: Metadata[] = [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [[startY]], + label: 'H', + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [[startY + classicalRegHeight * 3]], + label: 'H', + width: minGateWidth, + }, + ]; + const expectedWidth: number = startX + minGateWidth + gatePadding * 2; + const { metadataList, svgWidth } = processOperations(operations, registers); + expect(metadataList).toEqual(expectedOps); + expect(svgWidth).toEqual(expectedWidth); + }); + test('no operations', () => { + const operations: Operation[] = []; + const registers: RegisterMap = {}; + const { metadataList, svgWidth } = processOperations(operations, registers); + expect(metadataList).toEqual([]); + expect(svgWidth).toEqual(startX); + }); +}); diff --git a/circuit_vis/__tests__/registerFormatter.test.ts b/circuit_vis/__tests__/registerFormatter.test.ts new file mode 100644 index 0000000000..9723bead0a --- /dev/null +++ b/circuit_vis/__tests__/registerFormatter.test.ts @@ -0,0 +1,165 @@ +import { formatRegisters, _classicalRegister, _qubitRegister } from '../src/formatters/registerFormatter'; +import { RegisterMap, RegisterType } from '../src/register'; +import { Metadata, GateType } from '../src/metadata'; +import { startY, registerHeight, classicalRegHeight, startX, minGateWidth } from '../src/constants'; + +describe('Testing _classicalRegister', () => { + test('register with normal width', () => { + expect(_classicalRegister(10, 10, 100, 20)).toMatchSnapshot(); + expect(_classicalRegister(10, 10, 100, 20)).toMatchSnapshot(); + expect(_classicalRegister(10, 10, 100, 20)).toMatchSnapshot(); + }); + test('register with small width', () => { + expect(_classicalRegister(10, 10, 5, 20)).toMatchSnapshot(); + expect(_classicalRegister(10, 10, 5, 20)).toMatchSnapshot(); + expect(_classicalRegister(10, 10, 5, 20)).toMatchSnapshot(); + }); + test('register with large width', () => { + expect(_classicalRegister(10, 10, 500, 20)).toMatchSnapshot(); + expect(_classicalRegister(10, 10, 500, 20)).toMatchSnapshot(); + expect(_classicalRegister(10, 10, 500, 20)).toMatchSnapshot(); + }); + test('register with label offset', () => { + expect(_classicalRegister(10, 10, 100, 20)).toMatchSnapshot(); + expect(_classicalRegister(10, 10, 100, 20)).toMatchSnapshot(); + expect(_classicalRegister(10, 10, 100, 20)).toMatchSnapshot(); + }); +}); + +describe('Testing _qubitRegister', () => { + test('register with normal width', () => { + expect(_qubitRegister(0, 100, 20)).toMatchSnapshot(); + expect(_qubitRegister(1, 100, 20)).toMatchSnapshot(); + expect(_qubitRegister(2, 100, 20)).toMatchSnapshot(); + }); + test('register with small width', () => { + expect(_qubitRegister(0, 5, 20)).toMatchSnapshot(); + expect(_qubitRegister(1, 5, 20)).toMatchSnapshot(); + expect(_qubitRegister(2, 5, 20)).toMatchSnapshot(); + }); + test('register with large width', () => { + expect(_qubitRegister(0, 500, 20)).toMatchSnapshot(); + expect(_qubitRegister(1, 500, 20)).toMatchSnapshot(); + expect(_qubitRegister(2, 500, 20)).toMatchSnapshot(); + }); + test('register with label offset', () => { + expect(_qubitRegister(0, 100, 20, 0)).toMatchSnapshot(); + expect(_qubitRegister(1, 100, 20, 5)).toMatchSnapshot(); + expect(_qubitRegister(2, 100, 20, 50)).toMatchSnapshot(); + }); +}); + +describe('Testing formatRegisters', () => { + test('1 quantum register', () => { + const registers: RegisterMap = { 0: { type: RegisterType.Qubit, y: startY } }; + // Normal width + expect(formatRegisters(registers, [], startX + 100)).toMatchSnapshot(); + // Small width + expect(formatRegisters(registers, [], startX + 5)).toMatchSnapshot(); + // Large width + expect(formatRegisters(registers, [], startX + 500)).toMatchSnapshot(); + }); + test('Multiple quantum registers', () => { + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, + 3: { type: RegisterType.Qubit, y: startY + registerHeight * 3 }, + }; + // Normal width + expect(formatRegisters(registers, [], startX + 100)).toMatchSnapshot(); + // Small width + expect(formatRegisters(registers, [], startX + 5)).toMatchSnapshot(); + // Large width + expect(formatRegisters(registers, [], startX + 500)).toMatchSnapshot(); + }); + test('Skipped quantum registers', () => { + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, + 3: { type: RegisterType.Qubit, y: startY + registerHeight * 3 }, + }; + // Normal width + expect(formatRegisters(registers, [], startX + 100)).toMatchSnapshot(); + // Small width + expect(formatRegisters(registers, [], startX + 5)).toMatchSnapshot(); + // Large width + expect(formatRegisters(registers, [], startX + 500)).toMatchSnapshot(); + }); + test('Quantum and classical registers', () => { + let registers: RegisterMap = { + 0: { + type: RegisterType.Qubit, + y: startY, + children: [{ type: RegisterType.Classical, y: startY + classicalRegHeight }], + }, + 1: { type: RegisterType.Qubit, y: startY + classicalRegHeight * 2 }, + 2: { type: RegisterType.Qubit, y: startY + registerHeight + classicalRegHeight * 2 }, + }; + let measureGates: Metadata[] = [ + { + type: GateType.Measure, + x: startX, + controlsY: [startY], + targetsY: [startY + classicalRegHeight], + label: '', + width: minGateWidth, + }, + ]; + // Normal width + expect(formatRegisters(registers, measureGates, startX + 100)).toMatchSnapshot(); + // Small width + expect(formatRegisters(registers, measureGates, startX + 5)).toMatchSnapshot(); + // Large width + expect(formatRegisters(registers, measureGates, startX + 500)).toMatchSnapshot(); + + registers = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { + type: RegisterType.Qubit, + y: startY + registerHeight, + children: [ + { type: RegisterType.Classical, y: startY + registerHeight + classicalRegHeight }, + { type: RegisterType.Classical, y: startY + registerHeight + classicalRegHeight * 2 }, + ], + }, + 2: { + type: RegisterType.Qubit, + y: startY + registerHeight + classicalRegHeight * 3, + children: [{ type: RegisterType.Classical, y: startY + registerHeight + classicalRegHeight * 4 }], + }, + }; + measureGates = [ + { + type: GateType.Measure, + x: startX, + controlsY: [startY], + targetsY: [startY + classicalRegHeight], + label: '', + width: minGateWidth, + }, + { + type: GateType.Measure, + x: startX, + controlsY: [startY], + targetsY: [startY + classicalRegHeight * 2], + label: '', + width: minGateWidth, + }, + { + type: GateType.Measure, + x: startX, + controlsY: [startY + classicalRegHeight * 3], + targetsY: [startY + classicalRegHeight * 4], + label: '', + width: minGateWidth, + }, + ]; + // Normal width + expect(formatRegisters(registers, measureGates, startX + 100)).toMatchSnapshot(); + // Small width + expect(formatRegisters(registers, measureGates, startX + 5)).toMatchSnapshot(); + // Large width + expect(formatRegisters(registers, measureGates, startX + 500)).toMatchSnapshot(); + }); +}); diff --git a/circuit_vis/__tests__/utils.test.ts b/circuit_vis/__tests__/utils.test.ts new file mode 100644 index 0000000000..23889c0b77 --- /dev/null +++ b/circuit_vis/__tests__/utils.test.ts @@ -0,0 +1,51 @@ +import { getGateWidth, _getStringWidth, createUUID } from '../src/utils'; +import { minGateWidth, labelPadding } from '../src/constants'; +import { GateType } from '../src/metadata'; + +describe('Testing createUUID', () => { + test('no x in uuid', () => expect(createUUID()).not.toContain('x')); + test('no y in uuid', () => expect(createUUID()).not.toContain('y')); +}); + +describe('Testing getGateWidth', () => { + test('measure gate', () => + expect(getGateWidth(Object.assign({ type: GateType.Measure, label: '' }))).toEqual(minGateWidth)); + test('cnot gate', () => + expect(getGateWidth(Object.assign({ type: GateType.Cnot, label: 'x' }))).toEqual(minGateWidth)); + test('swap gate', () => + expect(getGateWidth(Object.assign({ type: GateType.Swap, label: '' }))).toEqual(minGateWidth)); + test('single unitary gate', () => + expect(getGateWidth(Object.assign({ type: GateType.Unitary, label: 'x' }))).toEqual(minGateWidth)); + test('multi unitary gate', () => + expect(getGateWidth(Object.assign({ type: GateType.Unitary, label: 'zz' }))).toEqual(minGateWidth)); + test('unitary gate with arguments', () => + expect(getGateWidth(Object.assign({ type: GateType.Unitary, displayArgs: '(0.25)', label: 'RX' }))).toEqual( + 52, + )); + test('invalid', () => + expect(getGateWidth(Object.assign({ type: GateType.Invalid, label: '' }))).toEqual(minGateWidth)); + test('unitary with long name', () => + expect(getGateWidth(Object.assign({ type: GateType.Unitary, label: 'FOOBAR' }))).toBeCloseTo( + 59 + labelPadding * 2, + )); + test('classically controlled gate', () => { + expect(getGateWidth(Object.assign({ type: GateType.ClassicalControlled, label: '', width: 500 }))).toEqual(500); + }); +}); + +describe('Testing _getStringWidth', () => { + test('correctly scaled width with font size', () => { + expect(_getStringWidth('FOOBAR', 14)).toEqual(59); + expect(_getStringWidth('FOOBAR', 20)).toEqual(84); + expect(_getStringWidth('FOOBAR', 5)).toEqual(21); + expect(_getStringWidth('FOOBAR', 100)).toEqual(423); + expect(_getStringWidth('FOOBAR', 200)).toEqual(844); + }); + + test('varying size strings', () => { + expect(_getStringWidth('H', 14)).toBeGreaterThanOrEqual(9); + expect(_getStringWidth('H', 14)).toBeLessThanOrEqual(10); + expect(_getStringWidth('GateWithASuperLongName', 14)).toBeGreaterThanOrEqual(174); + expect(_getStringWidth('GateWithASuperLongName', 14)).toBeLessThanOrEqual(176); + }); +}); diff --git a/circuit_vis/example/circuits.js b/circuit_vis/example/circuits.js new file mode 100644 index 0000000000..8345e82615 --- /dev/null +++ b/circuit_vis/example/circuits.js @@ -0,0 +1,1671 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +/* eslint-disable @typescript-eslint/no-unused-vars */ + +// Basic example: entanglement with measurement +//export +const entangle = { + qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], + operations: [ + { + gate: 'H', + targets: [{ qId: 0 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + }, + { + gate: 'Measure', + isMeasurement: true, + controls: [{ qId: 1 }], + targets: [{ type: 1, qId: 1, cId: 0 }], + }, + ], +}; + +// Sample circuit +//export +const sample = { + qubits: [{ id: 0, numChildren: 1 }, { id: 1 }, { id: 2 }, { id: 3 }], + operations: [ + { + gate: 'Foo', + conditionalRender: 3, + targets: [{ qId: 0 }, { qId: 1 }], + children: [ + { + gate: 'H', + targets: [{ qId: 1 }], + }, + { + gate: 'RX', + displayArgs: '(0.25)', + isControlled: true, + controls: [{ qId: 1 }], + targets: [{ qId: 0 }], + }, + ], + }, + { + gate: 'X', + targets: [{ qId: 3 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 1 }], + targets: [{ qId: 2 }, { qId: 3 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 2 }, { qId: 3 }], + targets: [{ qId: 1 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 1 }, { qId: 3 }], + targets: [{ qId: 2 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 2 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'measure', + isMeasurement: true, + controls: [{ qId: 0 }], + targets: [{ type: 1, qId: 0, cId: 0 }], + }, + { + gate: 'ApplyIfElseR', + isConditional: true, + controls: [{ type: 1, qId: 0, cId: 0 }], + targets: [], + children: [ + { + gate: 'H', + targets: [{ qId: 1 }], + conditionalRender: 1, + }, + { + gate: 'X', + targets: [{ qId: 1 }], + conditionalRender: 1, + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + conditionalRender: 2, + }, + { + gate: 'Foo', + targets: [{ qId: 3 }], + conditionalRender: 2, + }, + ], + }, + { + gate: 'SWAP', + targets: [{ qId: 0 }, { qId: 2 }], + children: [ + { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, + { gate: 'X', isControlled: true, controls: [{ qId: 2 }], targets: [{ qId: 0 }] }, + { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, + ], + }, + { + gate: 'ZZ', + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'ZZ', + targets: [{ qId: 0 }, { qId: 1 }], + }, + { + gate: 'XX', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'XX', + isControlled: true, + controls: [{ qId: 2 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'XX', + isControlled: true, + controls: [{ qId: 0 }, { qId: 2 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + ], +}; + +// Teleportation algorithm +//export +const teleport = { + qubits: [ + { + id: 0, + numChildren: 1, + }, + { + id: 1, + numChildren: 1, + }, + { + id: 2, + }, + ], + operations: [ + { + gate: 'Teleport', + children: [ + { + gate: 'Entangle', + children: [ + { + gate: 'H', + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: 'X', + isControlled: true, + controls: [ + { + qId: 1, + }, + ], + targets: [ + { + qId: 2, + }, + ], + }, + ], + targets: [ + { + qId: 1, + }, + { + qId: 2, + }, + ], + }, + { + gate: 'PrepareMessage', + children: [ + { + gate: 'Random', + displayArgs: '([0.5, 0.5])', + children: [ + { + gate: 'DrawCategorical', + displayArgs: '([0.5, 0.5])', + children: [ + { + gate: 'DrawRandomDouble', + displayArgs: '(0, 1)', + targets: [], + }, + ], + targets: [], + }, + ], + targets: [], + }, + { + gate: 'SetPlus', + children: [ + { + gate: 'H', + targets: [ + { + qId: 0, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: 'Encode', + children: [ + { + gate: 'X', + isControlled: true, + controls: [ + { + qId: 0, + }, + ], + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: 'H', + targets: [ + { + qId: 0, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + ], + }, + { + gate: 'M', + isMeasurement: true, + controls: [ + { + qId: 0, + }, + ], + targets: [ + { + type: 1, + qId: 0, + cId: 0, + }, + ], + }, + { + gate: 'measure', + isMeasurement: true, + controls: [ + { + qId: 1, + }, + ], + targets: [ + { + type: 1, + qId: 1, + cId: 0, + }, + ], + }, + { + gate: 'Decode', + children: [ + { + gate: 'ApplyIfElseR', + isConditional: true, + controls: [ + { + type: 1, + qId: 1, + cId: 0, + }, + ], + targets: [], + children: [ + { + gate: 'X', + controls: [ + { + type: 1, + qId: 1, + cId: 0, + }, + ], + targets: [ + { + qId: 2, + }, + ], + conditionalRender: 2, + }, + ], + }, + { + gate: 'ApplyIfElseR', + isConditional: true, + controls: [ + { + type: 1, + qId: 0, + cId: 0, + }, + ], + targets: [], + children: [ + { + gate: 'Z', + controls: [ + { + type: 1, + qId: 0, + cId: 0, + }, + ], + targets: [ + { + qId: 2, + }, + ], + conditionalRender: 2, + }, + ], + }, + ], + controls: [ + { + type: 1, + qId: 0, + cId: 0, + }, + { + type: 1, + qId: 1, + cId: 0, + }, + ], + targets: [ + { + qId: 2, + }, + ], + }, + ], + targets: [ + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 0, + }, + ], + }, + ], +}; + +// Grover's algorithm +//export +const grover = { + qubits: [ + { + id: 0, + numChildren: 1, + }, + { + id: 1, + numChildren: 1, + }, + { + id: 2, + numChildren: 1, + }, + { + id: 3, + numChildren: 1, + }, + { + id: 4, + }, + ], + operations: [ + { + gate: 'GroverSearch', + children: [ + { + gate: 'PrepareSuperposition', + children: [ + { + gate: 'H', + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: 'H', + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: 'H', + targets: [ + { + qId: 2, + }, + ], + }, + { + gate: 'H', + targets: [ + { + qId: 3, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + ], + }, + { + gate: 'GroverIteration', + displayArgs: '(Oracle)', + children: [ + { + gate: 'Oracle', + displayArgs: '(Oracle_6)', + children: [ + { + gate: 'X', + targets: [ + { + qId: 4, + }, + ], + }, + { + gate: 'H', + targets: [ + { + qId: 4, + }, + ], + }, + { + gate: 'Oracle_6', + children: [ + { + gate: 'X', + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: 'X', + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: 'X', + isControlled: true, + controls: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + ], + targets: [ + { + qId: 4, + }, + ], + }, + { + gate: 'X', + isAdjoint: true, + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: 'X', + isAdjoint: true, + targets: [ + { + qId: 0, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + { + qId: 4, + }, + ], + }, + { + gate: 'H', + isAdjoint: true, + targets: [ + { + qId: 4, + }, + ], + }, + { + gate: 'X', + isAdjoint: true, + targets: [ + { + qId: 4, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + { + qId: 4, + }, + ], + }, + { + gate: 'Diffuser', + children: [ + { + gate: 'H', + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: 'H', + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: 'H', + targets: [ + { + qId: 2, + }, + ], + }, + { + gate: 'H', + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: 'ConditionalPhaseFlip', + children: [ + { + gate: 'X', + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: 'X', + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: 'X', + targets: [ + { + qId: 2, + }, + ], + }, + { + gate: 'X', + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: 'Z', + isControlled: true, + controls: [ + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + ], + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: 'R', + displayArgs: '(PauliI, 3.141592653589793)', + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: 'X', + isAdjoint: true, + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: 'X', + isAdjoint: true, + targets: [ + { + qId: 2, + }, + ], + }, + { + gate: 'X', + isAdjoint: true, + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: 'X', + isAdjoint: true, + targets: [ + { + qId: 0, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + ], + }, + { + gate: 'H', + isAdjoint: true, + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: 'H', + isAdjoint: true, + targets: [ + { + qId: 2, + }, + ], + }, + { + gate: 'H', + isAdjoint: true, + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: 'H', + isAdjoint: true, + targets: [ + { + qId: 0, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + { + qId: 4, + }, + ], + }, + { + gate: 'GroverIteration', + displayArgs: '(Oracle)', + children: [ + { + gate: 'Oracle', + displayArgs: '(Oracle_6)', + children: [ + { + gate: 'X', + targets: [ + { + qId: 4, + }, + ], + }, + { + gate: 'H', + targets: [ + { + qId: 4, + }, + ], + }, + { + gate: 'Oracle_6', + children: [ + { + gate: 'X', + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: 'X', + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: 'X', + isControlled: true, + controls: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + ], + targets: [ + { + qId: 4, + }, + ], + }, + { + gate: 'X', + isAdjoint: true, + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: 'X', + isAdjoint: true, + targets: [ + { + qId: 0, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + { + qId: 4, + }, + ], + }, + { + gate: 'H', + isAdjoint: true, + targets: [ + { + qId: 4, + }, + ], + }, + { + gate: 'X', + isAdjoint: true, + targets: [ + { + qId: 4, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + { + qId: 4, + }, + ], + }, + { + gate: 'Diffuser', + children: [ + { + gate: 'H', + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: 'H', + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: 'H', + targets: [ + { + qId: 2, + }, + ], + }, + { + gate: 'H', + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: 'ConditionalPhaseFlip', + children: [ + { + gate: 'X', + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: 'X', + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: 'X', + targets: [ + { + qId: 2, + }, + ], + }, + { + gate: 'X', + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: 'Z', + isControlled: true, + controls: [ + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + ], + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: 'R', + displayArgs: '(PauliI, 3.141592653589793)', + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: 'X', + isAdjoint: true, + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: 'X', + isAdjoint: true, + targets: [ + { + qId: 2, + }, + ], + }, + { + gate: 'X', + isAdjoint: true, + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: 'X', + isAdjoint: true, + targets: [ + { + qId: 0, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + ], + }, + { + gate: 'H', + isAdjoint: true, + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: 'H', + isAdjoint: true, + targets: [ + { + qId: 2, + }, + ], + }, + { + gate: 'H', + isAdjoint: true, + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: 'H', + isAdjoint: true, + targets: [ + { + qId: 0, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + { + qId: 4, + }, + ], + }, + { + gate: 'GroverIteration', + displayArgs: '(Oracle)', + children: [ + { + gate: 'Oracle', + displayArgs: '(Oracle_6)', + children: [ + { + gate: 'X', + targets: [ + { + qId: 4, + }, + ], + }, + { + gate: 'H', + targets: [ + { + qId: 4, + }, + ], + }, + { + gate: 'Oracle_6', + children: [ + { + gate: 'X', + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: 'X', + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: 'X', + isControlled: true, + controls: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + ], + targets: [ + { + qId: 4, + }, + ], + }, + { + gate: 'X', + isAdjoint: true, + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: 'X', + isAdjoint: true, + targets: [ + { + qId: 0, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + { + qId: 4, + }, + ], + }, + { + gate: 'H', + isAdjoint: true, + targets: [ + { + qId: 4, + }, + ], + }, + { + gate: 'X', + isAdjoint: true, + targets: [ + { + qId: 4, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + { + qId: 4, + }, + ], + }, + { + gate: 'Diffuser', + children: [ + { + gate: 'H', + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: 'H', + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: 'H', + targets: [ + { + qId: 2, + }, + ], + }, + { + gate: 'H', + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: 'ConditionalPhaseFlip', + children: [ + { + gate: 'X', + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: 'X', + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: 'X', + targets: [ + { + qId: 2, + }, + ], + }, + { + gate: 'X', + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: 'Z', + isControlled: true, + controls: [ + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + ], + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: 'R', + displayArgs: '(PauliI, 3.141592653589793)', + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: 'X', + isAdjoint: true, + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: 'X', + isAdjoint: true, + targets: [ + { + qId: 2, + }, + ], + }, + { + gate: 'X', + isAdjoint: true, + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: 'X', + isAdjoint: true, + targets: [ + { + qId: 0, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + ], + }, + { + gate: 'H', + isAdjoint: true, + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: 'H', + isAdjoint: true, + targets: [ + { + qId: 2, + }, + ], + }, + { + gate: 'H', + isAdjoint: true, + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: 'H', + isAdjoint: true, + targets: [ + { + qId: 0, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + { + qId: 4, + }, + ], + }, + { + gate: 'M', + isMeasurement: true, + controls: [ + { + qId: 0, + }, + ], + targets: [ + { + type: 1, + qId: 0, + cId: 0, + }, + ], + }, + { + gate: 'M', + isMeasurement: true, + controls: [ + { + qId: 1, + }, + ], + targets: [ + { + type: 1, + qId: 1, + cId: 0, + }, + ], + }, + { + gate: 'M', + isMeasurement: true, + controls: [ + { + qId: 2, + }, + ], + targets: [ + { + type: 1, + qId: 2, + cId: 0, + }, + ], + }, + { + gate: 'M', + isMeasurement: true, + controls: [ + { + qId: 3, + }, + ], + targets: [ + { + type: 1, + qId: 3, + cId: 0, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + { + qId: 4, + }, + ], + }, + ], +}; diff --git a/circuit_vis/example/index.html b/circuit_vis/example/index.html new file mode 100644 index 0000000000..c3060fdda3 --- /dev/null +++ b/circuit_vis/example/index.html @@ -0,0 +1,58 @@ + + + + + + + + quantum-viz.js Demo + + + + + + + +
+

quantum-viz.js

+
+ Please make sure the project is built first by following the + Running from source instructions from the README.md +
+ +
+

1. Entangle

+
+
+

2. Sample

+
+

3. Teleport

+
+

4. Grover

+
+
+
+ + + diff --git a/circuit_vis/example/script.js b/circuit_vis/example/script.js new file mode 100644 index 0000000000..f6d62df9f7 --- /dev/null +++ b/circuit_vis/example/script.js @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +if (typeof qviz != 'undefined') { + document.getElementById('message').remove(); + + /* These examples shows how to draw circuits into containers. */ + const entangleDiv = document.getElementById('entangle'); + if (entangleDiv != null) { + qviz.draw(entangle, entangleDiv, qviz.STYLES['Default']); + } + + const sampleDiv = document.getElementById('sample'); + if (sampleDiv != null) { + qviz.draw(sample, sampleDiv, qviz.STYLES['Default']); + } + + const teleportDiv = document.getElementById('teleport'); + if (teleportDiv != null) { + qviz.draw(teleport, teleportDiv, qviz.STYLES['Default']); + } + + const groverDiv = document.getElementById('grover'); + if (groverDiv != null) { + qviz.draw(grover, groverDiv, qviz.STYLES['Default']); + } +} else { + document.getElementById('group').remove(); +} diff --git a/circuit_vis/jest.config.js b/circuit_vis/jest.config.js new file mode 100644 index 0000000000..c0432e2a85 --- /dev/null +++ b/circuit_vis/jest.config.js @@ -0,0 +1,8 @@ +module.exports = { + roots: [''], + transform: { + '^.+\\.tsx?$': 'ts-jest', + }, + testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$', + moduleFileExtensions: ['ts', 'js'], +}; diff --git a/circuit_vis/package.json b/circuit_vis/package.json new file mode 100644 index 0000000000..fb95e59ebf --- /dev/null +++ b/circuit_vis/package.json @@ -0,0 +1,53 @@ +{ + "name": "@microsoft/quantum-viz.js", + "version": "1.0.6", + "description": "quantum-viz.js is a configurable tool for visualizing quantum circuits.", + "main": "dist/qviz.min.js", + "scripts": { + "build": "tsc", + "build:prod": "tsc && webpack", + "coverage": "jest --coverage", + "lint": "eslint .", + "lint:fix": "eslint . --fix", + "prepublishOnly": "npm run lint && npm run test && npm run build:prod", + "start": "tsc -w", + "test": "jest" + }, + "files": [ + "README.md", + "LICENSE.txt", + "lib", + "dist" + ], + "repository": { + "type": "git", + "url": "https://github.com/microsoft/quantum-viz.js" + }, + "keywords": [ + "quantum", + "circuits", + "visualization" + ], + "author": "Microsoft Quantum", + "license": "MIT", + "devDependencies": { + "@types/jest": "^26.0.4", + "@types/prettier": "2.6.0", + "@typescript-eslint/eslint-plugin": "^3.9.0", + "@typescript-eslint/parser": "^3.9.0", + "canvas": "^2.6.1", + "eslint": "^7.6.0", + "eslint-config-prettier": "^6.11.0", + "eslint-plugin-jest": "^23.20.0", + "eslint-plugin-prettier": "^3.1.4", + "jest": "^26.6.3", + "prettier": "2.6.0", + "terser-webpack-plugin": "^4.1.0", + "ts-jest": "^26.1.2", + "ts-loader": "^8.0.2", + "typescript": "^4.9.4", + "webpack": "^5.75.0", + "webpack-cli": "^5.0.1" + }, + "homepage": "https://github.com/microsoft/quantum-viz.js#readme" +} diff --git a/circuit_vis/src/circuit.ts b/circuit_vis/src/circuit.ts new file mode 100644 index 0000000000..685215e3f3 --- /dev/null +++ b/circuit_vis/src/circuit.ts @@ -0,0 +1,72 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import { Register } from './register'; + +/** + * Circuit to be visualized. + */ +export interface Circuit { + /** Array of qubit resources. */ + qubits: Qubit[]; + operations: Operation[]; +} + +/** + * Represents a unique qubit resource bit. + */ +export interface Qubit { + /** Qubit ID. */ + id: number; + /** Number of classical registers attached to quantum register. */ + numChildren?: number; +} + +/** + * Conditions on when to render the given operation. + */ +export enum ConditionalRender { + /** Always rendered. */ + Always, + /** Render classically-controlled operation when measurement is a zero. */ + OnZero, + /** Render classically-controlled operation when measurement is a one. */ + OnOne, + /** Render operation as a group of its nested operations. */ + AsGroup, +} + +/** + * Custom data attributes (e.g. data-{attr}="{val}") + */ +export interface DataAttributes { + [attr: string]: string; +} + +/** + * Represents an operation and the registers it acts on. + */ +export interface Operation { + /** Gate label. */ + gate: string; + /** Formatted gate arguments to be displayed. */ + displayArgs?: string; + /** Nested operations within this operation. */ + children?: Operation[]; + /** Whether gate is a measurement operation. */ + isMeasurement: boolean; + /** Whether gate is a conditional operation. */ + isConditional: boolean; + /** Whether gate is a controlled operation. */ + isControlled: boolean; + /** Whether gate is an adjoint operation. */ + isAdjoint: boolean; + /** Control registers the gate acts on. */ + controls?: Register[]; + /** Target registers the gate acts on. */ + targets: Register[]; + /** Specify conditions on when to render operation. */ + conditionalRender?: ConditionalRender; + /** Custom data attributes to attach to gate element. */ + dataAttributes?: DataAttributes; +} diff --git a/circuit_vis/src/constants.ts b/circuit_vis/src/constants.ts new file mode 100644 index 0000000000..2ccb9e331f --- /dev/null +++ b/circuit_vis/src/constants.ts @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +// SVG Namespace +export const svgNS = 'http://www.w3.org/2000/svg'; + +// Display attributes +/** Left padding of SVG. */ +export const leftPadding = 20; +/** x coordinate for first operation on each register. */ +export const startX = 80; +/** y coordinate of first register. */ +export const startY = 40; +/** Minimum width of each gate. */ +export const minGateWidth = 40; +/** Height of each gate. */ +export const gateHeight = 40; +/** Padding on each side of gate. */ +export const gatePadding = 10; +/** Padding on each side of gate label. */ +export const labelPadding = 10; +/** Height between each qubit register. */ +export const registerHeight: number = gateHeight + gatePadding * 2; +/** Height between classical registers. */ +export const classicalRegHeight: number = gateHeight; +/** Group box inner padding. */ +export const groupBoxPadding = gatePadding; +/** Padding between nested groups. */ +export const nestedGroupPadding = 2; +/** Additional offset for control button. */ +export const controlBtnOffset = 40; +/** Control button radius. */ +export const controlBtnRadius = 15; +/** Default font size for gate labels. */ +export const labelFontSize = 14; +/** Default font size for gate arguments. */ +export const argsFontSize = 12; +/** Starting x coord for each register wire. */ +export const regLineStart = 40; diff --git a/circuit_vis/src/formatters/formatUtils.ts b/circuit_vis/src/formatters/formatUtils.ts new file mode 100644 index 0000000000..99b4ffa482 --- /dev/null +++ b/circuit_vis/src/formatters/formatUtils.ts @@ -0,0 +1,177 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import { labelFontSize, svgNS } from '../constants'; + +// Helper functions for basic SVG components + +/** + * Create an SVG element. + * + * @param type The type of element to be created. + * @param attributes The attributes that define the element. + * + * @returns SVG element. + */ +export const createSvgElement = (type: string, attributes: { [attr: string]: string } = {}): SVGElement => { + const el: SVGElement = document.createElementNS(svgNS, type); + Object.entries(attributes).forEach(([attrName, attrVal]) => el.setAttribute(attrName, attrVal)); + return el; +}; + +/** + * Given an array of SVG elements, group them as an SVG group using the `` tag. + * + * @param svgElems Array of SVG elements. + * @param attributes Key-value pairs of attributes and they values. + * + * @returns SVG element for grouped elements. + */ +export const group = (svgElems: SVGElement[], attributes: { [attr: string]: string } = {}): SVGElement => { + const el: SVGElement = createSvgElement('g', attributes); + svgElems.forEach((child: SVGElement) => el.appendChild(child)); + return el; +}; + +/** + * Generate an SVG line. + * + * @param x1 x coord of starting point of line. + * @param y1 y coord of starting point of line. + * @param x2 x coord of ending point of line. + * @param y2 y coord fo ending point of line. + * @param className Class name of element. + * + * @returns SVG element for line. + */ +export const line = (x1: number, y1: number, x2: number, y2: number, className?: string): SVGElement => { + const attrs: { [attr: string]: string } = { + x1: x1.toString(), + x2: x2.toString(), + y1: y1.toString(), + y2: y2.toString(), + }; + if (className != null) attrs['class'] = className; + return createSvgElement('line', attrs); +}; + +/** + * Generate an SVG circle. + * + * @param x x coord of circle. + * @param y y coord of circle. + * @param radius Radius of circle. + * + * @returns SVG element for circle. + */ +export const circle = (x: number, y: number, radius: number, className?: string): SVGElement => { + const attrs: { [attr: string]: string } = { + cx: x.toString(), + cy: y.toString(), + r: radius.toString(), + }; + if (className != null) attrs['class'] = className; + return createSvgElement('circle', attrs); +}; + +/** + * Generate the SVG representation of a control dot used for controlled operations. + * + * @param x x coord of circle. + * @param y y coord of circle. + * @param radius Radius of circle. + * + * @returns SVG element for control dot. + */ +export const controlDot = (x: number, y: number, radius = 5): SVGElement => circle(x, y, radius, 'control-dot'); + +/** + * Generate the SVG representation of a unitary box that represents an arbitrary unitary operation. + * + * @param x x coord of box. + * @param y y coord of box. + * @param width Width of box. + * @param height Height of box. + * @param className Class name of element. + * + * @returns SVG element for unitary box. + */ +export const box = (x: number, y: number, width: number, height: number, className = 'gate-unitary'): SVGElement => + createSvgElement('rect', { + class: className, + x: x.toString(), + y: y.toString(), + width: width.toString(), + height: height.toString(), + }); + +/** + * Generate the SVG text element from a given text string. + * + * @param text String to render as SVG text. + * @param x Middle x coord of text. + * @param y Middle y coord of text. + * @param fs Font size of text. + * + * @returns SVG element for text. + */ +export const text = (text: string, x: number, y: number, fs: number = labelFontSize): SVGElement => { + const el: SVGElement = createSvgElement('text', { + 'font-size': fs.toString(), + x: x.toString(), + y: y.toString(), + }); + el.textContent = text; + return el; +}; + +/** + * Generate the SVG representation of the arc used in the measurement box. + * + * @param x x coord of arc. + * @param y y coord of arc. + * @param rx x radius of arc. + * @param ry y radius of arc. + * + * @returns SVG element for arc. + */ +export const arc = (x: number, y: number, rx: number, ry: number): SVGElement => + createSvgElement('path', { + class: 'arc-measure', + d: `M ${x + 2 * rx} ${y} A ${rx} ${ry} 0 0 0 ${x} ${y}`, + }); + +/** + * Generate a dashed SVG line. + * + * @param x1 x coord of starting point of line. + * @param y1 y coord of starting point of line. + * @param x2 x coord of ending point of line. + * @param y2 y coord fo ending point of line. + * @param className Class name of element. + * + * @returns SVG element for dashed line. + */ +export const dashedLine = (x1: number, y1: number, x2: number, y2: number, className?: string): SVGElement => { + const el: SVGElement = line(x1, y1, x2, y2, className); + el.setAttribute('stroke-dasharray', '8, 8'); + return el; +}; + +/** + * Generate the SVG representation of the dashed box used for enclosing groups of operations controlled on a classical register. + * + * @param x x coord of box. + * @param y y coord of box. + * @param width Width of box. + * @param height Height of box. + * @param className Class name of element. + * + * @returns SVG element for dashed box. + */ +export const dashedBox = (x: number, y: number, width: number, height: number, className?: string): SVGElement => { + const el: SVGElement = box(x, y, width, height, className); + el.setAttribute('fill-opacity', '0'); + el.setAttribute('stroke-dasharray', '8, 8'); + return el; +}; diff --git a/circuit_vis/src/formatters/gateFormatter.ts b/circuit_vis/src/formatters/gateFormatter.ts new file mode 100644 index 0000000000..16588ff3d4 --- /dev/null +++ b/circuit_vis/src/formatters/gateFormatter.ts @@ -0,0 +1,467 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import { Metadata, GateType } from '../metadata'; +import { + minGateWidth, + gateHeight, + labelFontSize, + argsFontSize, + controlBtnRadius, + controlBtnOffset, + groupBoxPadding, + classicalRegHeight, + nestedGroupPadding, +} from '../constants'; +import { + createSvgElement, + group, + line, + circle, + controlDot, + box, + text, + arc, + dashedLine, + dashedBox, +} from './formatUtils'; + +/** + * Given an array of operations (in metadata format), return the SVG representation. + * + * @param opsMetadata Array of Metadata representation of operations. + * @param nestedDepth Depth of nested operations (used in classically controlled and grouped operations). + * + * @returns SVG representation of operations. + */ +const formatGates = (opsMetadata: Metadata[], nestedDepth = 0): SVGElement => { + const formattedGates: SVGElement[] = opsMetadata.map((metadata) => _formatGate(metadata, nestedDepth)); + return group(formattedGates); +}; + +/** + * Takes in an operation's metadata and formats it into SVG. + * + * @param metadata Metadata object representation of gate. + * @param nestedDepth Depth of nested operations (used in classically controlled and grouped operations). + * + * @returns SVG representation of gate. + */ +const _formatGate = (metadata: Metadata, nestedDepth = 0): SVGElement => { + const { type, x, controlsY, targetsY, label, displayArgs, width } = metadata; + switch (type) { + case GateType.Measure: + return _createGate([_measure(x, controlsY[0])], metadata, nestedDepth); + case GateType.Unitary: + return _createGate([_unitary(label, x, targetsY as number[][], width, displayArgs)], metadata, nestedDepth); + case GateType.X: + return _createGate([_x(metadata, nestedDepth)], metadata, nestedDepth); + case GateType.Swap: + return controlsY.length > 0 + ? _controlledGate(metadata, nestedDepth) + : _createGate([_swap(metadata, nestedDepth)], metadata, nestedDepth); + case GateType.Cnot: + case GateType.ControlledUnitary: + return _controlledGate(metadata, nestedDepth); + case GateType.Group: + return _groupedOperations(metadata, nestedDepth); + case GateType.ClassicalControlled: + return _classicalControlled(metadata); + default: + throw new Error(`ERROR: unknown gate (${label}) of type ${type}.`); + } +}; + +/** + * Groups SVG elements into a gate SVG group. + * + * @param svgElems Array of SVG elements. + * @param dataAttributes Custom data attributes to be attached to SVG group. + * + * @returns SVG representation of a gate. + */ +const _createGate = (svgElems: SVGElement[], metadata: Metadata, nestedDepth: number): SVGElement => { + const { dataAttributes } = metadata || {}; + const attributes: { [attr: string]: string } = { class: 'gate' }; + Object.entries(dataAttributes || {}).forEach(([attr, val]) => (attributes[`data-${attr}`] = val)); + + const zoomBtn: SVGElement | null = _zoomButton(metadata, nestedDepth); + if (zoomBtn != null) svgElems = svgElems.concat([zoomBtn]); + return group(svgElems, attributes); +}; + +/** + * Returns the expand/collapse button for an operation if it can be zoomed-in or zoomed-out, + * respectively. If neither are allowed, return `null`. + * + * @param metadata Operation metadata. + * @param nestedDepth Depth of nested operation. + * + * @returns SVG element for expand/collapse button if needed, or null otherwise. + */ +const _zoomButton = (metadata: Metadata, nestedDepth: number): SVGElement | null => { + if (metadata == undefined) return null; + + const [x1, y1] = _gatePosition(metadata, nestedDepth); + let { dataAttributes } = metadata; + dataAttributes = dataAttributes || {}; + + const expanded = 'expanded' in dataAttributes; + + const x = x1 + 2; + const y = y1 + 2; + const circleBorder: SVGElement = circle(x, y, 10); + + if (expanded) { + // Create collapse button if expanded + const minusSign: SVGElement = createSvgElement('path', { d: `M${x - 7},${y} h14` }); + const elements: SVGElement[] = [circleBorder, minusSign]; + return group(elements, { class: 'gate-control gate-collapse' }); + } else if (dataAttributes['zoom-in'] == 'true') { + // Create expand button if operation can be zoomed in + const plusSign: SVGElement = createSvgElement('path', { d: `M${x},${y - 7} v14 M${x - 7},${y} h14` }); + const elements: SVGElement[] = [circleBorder, plusSign]; + return group(elements, { class: 'gate-control gate-expand' }); + } + + return null; +}; + +/** + * Calculate position of gate. + * + * @param metadata Operation metadata. + * @param nestedDepth Depth of nested operations. + * + * @returns Coordinates of gate: [x1, y1, x2, y2]. + */ +const _gatePosition = (metadata: Metadata, nestedDepth: number): [number, number, number, number] => { + const { x, width, type, targetsY } = metadata; + + const ys = targetsY?.flatMap((y) => y as number[]) || []; + const maxY = Math.max(...ys); + const minY = Math.min(...ys); + + let x1: number, y1: number, x2: number, y2: number; + + switch (type) { + case GateType.Group: + const padding = groupBoxPadding - nestedDepth * nestedGroupPadding; + + x1 = x - 2 * padding; + y1 = minY - gateHeight / 2 - padding; + x2 = width + 2 * padding; + y2 = maxY + +gateHeight / 2 + padding - (minY - gateHeight / 2 - padding); + + return [x1, y1, x2, y2]; + + default: + x1 = x - width / 2; + y1 = minY - gateHeight / 2; + x2 = x + width; + y2 = maxY + gateHeight / 2; + } + + return [x1, y1, x2, y2]; +}; + +/** + * Creates a measurement gate at position (x, y). + * + * @param x x coord of measurement gate. + * @param y y coord of measurement gate. + * + * @returns SVG representation of measurement gate. + */ +const _measure = (x: number, y: number): SVGElement => { + x -= minGateWidth / 2; + const width: number = minGateWidth, + height = gateHeight; + // Draw measurement box + const mBox: SVGElement = box(x, y - height / 2, width, height, 'gate-measure'); + const mArc: SVGElement = arc(x + 5, y + 2, width / 2 - 5, height / 2 - 8); + const meter: SVGElement = line(x + width / 2, y + 8, x + width - 8, y - height / 2 + 8); + return group([mBox, mArc, meter]); +}; + +/** + * Creates the SVG for a unitary gate on an arbitrary number of qubits. + * + * @param label Gate label. + * @param x x coord of gate. + * @param y Array of y coords of registers acted upon by gate. + * @param width Width of gate. + * @param displayArgs Arguments passed in to gate. + * @param renderDashedLine If true, draw dashed lines between non-adjacent unitaries. + * + * @returns SVG representation of unitary gate. + */ +const _unitary = ( + label: string, + x: number, + y: number[][], + width: number, + displayArgs?: string, + renderDashedLine = true, +): SVGElement => { + if (y.length === 0) throw new Error(`Failed to render unitary gate (${label}): has no y-values`); + + // Render each group as a separate unitary boxes + const unitaryBoxes: SVGElement[] = y.map((group: number[]) => { + const maxY: number = group[group.length - 1], + minY: number = group[0]; + const height: number = maxY - minY + gateHeight; + return _unitaryBox(label, x, minY, width, height, displayArgs); + }); + + // Draw dashed line between disconnected unitaries + if (renderDashedLine && unitaryBoxes.length > 1) { + const lastBox: number[] = y[y.length - 1]; + const firstBox: number[] = y[0]; + const maxY: number = lastBox[lastBox.length - 1], + minY: number = firstBox[0]; + const vertLine: SVGElement = dashedLine(x, minY, x, maxY); + return group([vertLine, ...unitaryBoxes]); + } + + return group(unitaryBoxes); +}; + +/** + * Generates SVG representation of the boxed unitary gate symbol. + * + * @param label Label for unitary operation. + * @param x x coord of gate. + * @param y y coord of gate. + * @param width Width of gate. + * @param height Height of gate. + * @param displayArgs Arguments passed in to gate. + * + * @returns SVG representation of unitary box. + */ +const _unitaryBox = ( + label: string, + x: number, + y: number, + width: number, + height: number = gateHeight, + displayArgs?: string, +): SVGElement => { + y -= gateHeight / 2; + const uBox: SVGElement = box(x - width / 2, y, width, height); + const labelY = y + height / 2 - (displayArgs == null ? 0 : 7); + const labelText: SVGElement = text(label, x, labelY); + const elems = [uBox, labelText]; + if (displayArgs != null) { + const argStrY = y + height / 2 + 8; + const argText: SVGElement = text(displayArgs, x, argStrY, argsFontSize); + elems.push(argText); + } + return group(elems); +}; + +/** + * Creates the SVG for a SWAP gate on y coords given by targetsY. + * + * @param x Centre x coord of SWAP gate. + * @param targetsY y coords of target registers. + * + * @returns SVG representation of SWAP gate. + */ +const _swap = (metadata: Metadata, nestedDepth: number): SVGElement => { + const { x, targetsY } = metadata; + + // Get SVGs of crosses + const [x1, y1, x2, y2] = _gatePosition(metadata, nestedDepth); + const ys = targetsY?.flatMap((y) => y as number[]) || []; + + const bg: SVGElement = box(x1, y1, x2, y2, 'gate-swap'); + const crosses: SVGElement[] = ys.map((y) => _cross(x, y)); + const vertLine: SVGElement = line(x, ys[0], x, ys[1]); + return group([bg, ...crosses, vertLine]); +}; +/** + * Creates the SVG for an X gate + * + * @returns SVG representation of X gate. + */ +const _x = (metadata: Metadata, _: number): SVGElement => { + const { x, targetsY } = metadata; + const ys = targetsY.flatMap((y) => y as number[]); + return _oplus(x, ys[0]); +}; +/** + * Generates cross for display in SWAP gate. + * + * @param x x coord of gate. + * @param y y coord of gate. + * + * @returns SVG representation for cross. + */ +const _cross = (x: number, y: number): SVGElement => { + const radius = 8; + const line1: SVGElement = line(x - radius, y - radius, x + radius, y + radius); + const line2: SVGElement = line(x - radius, y + radius, x + radius, y - radius); + return group([line1, line2]); +}; + +/** + * Produces the SVG representation of a controlled gate on multiple qubits. + * + * @param metadata Metadata of controlled gate. + * + * @returns SVG representation of controlled gate. + */ +const _controlledGate = (metadata: Metadata, nestedDepth: number): SVGElement => { + const targetGateSvgs: SVGElement[] = []; + const { type, x, controlsY, label, displayArgs, width } = metadata; + let { targetsY } = metadata; + + // Get SVG for target gates + switch (type) { + case GateType.Cnot: + (targetsY as number[]).forEach((y) => targetGateSvgs.push(_oplus(x, y))); + break; + case GateType.Swap: + (targetsY as number[]).forEach((y) => targetGateSvgs.push(_cross(x, y))); + break; + case GateType.ControlledUnitary: + const groupedTargetsY: number[][] = targetsY as number[][]; + targetGateSvgs.push(_unitary(label, x, groupedTargetsY, width, displayArgs, false)); + targetsY = targetsY.flat(); + break; + default: + throw new Error(`ERROR: Unrecognized gate: ${label} of type ${type}`); + } + // Get SVGs for control dots + const controlledDotsSvg: SVGElement[] = controlsY.map((y) => controlDot(x, y)); + // Create control lines + const maxY: number = Math.max(...controlsY, ...(targetsY as number[])); + const minY: number = Math.min(...controlsY, ...(targetsY as number[])); + const vertLine: SVGElement = line(x, minY, x, maxY); + const svg: SVGElement = _createGate([vertLine, ...controlledDotsSvg, ...targetGateSvgs], metadata, nestedDepth); + return svg; +}; + +/** + * Generates $\oplus$ symbol for display in CNOT gate. + * + * @param x x coordinate of gate. + * @param y y coordinate of gate. + * @param r radius of circle. + * + * @returns SVG representation of $\oplus$ symbol. + */ +const _oplus = (x: number, y: number, r = 15): SVGElement => { + const circleBorder: SVGElement = circle(x, y, r); + const vertLine: SVGElement = line(x, y - r, x, y + r); + const horLine: SVGElement = line(x - r, y, x + r, y); + return group([circleBorder, vertLine, horLine], { class: 'oplus' }); +}; + +/** + * Generates the SVG for a group of nested operations. + * + * @param metadata Metadata representation of gate. + * @param nestedDepth Depth of nested operations (used in classically controlled and grouped operations). + * + * @returns SVG representation of gate. + */ +const _groupedOperations = (metadata: Metadata, nestedDepth: number): SVGElement => { + const { children } = metadata; + const [x1, y1, x2, y2] = _gatePosition(metadata, nestedDepth); + + // Draw dashed box around children gates + const box: SVGElement = dashedBox(x1, y1, x2, y2); + const elems: SVGElement[] = [box]; + if (children != null) elems.push(formatGates(children as Metadata[], nestedDepth + 1)); + return _createGate(elems, metadata, nestedDepth); +}; + +/** + * Generates the SVG for a classically controlled group of operations. + * + * @param metadata Metadata representation of gate. + * @param padding Padding within dashed box. + * + * @returns SVG representation of gate. + */ +const _classicalControlled = (metadata: Metadata, padding: number = groupBoxPadding): SVGElement => { + const { controlsY, dataAttributes } = metadata; + const targetsY: number[] = metadata.targetsY as number[]; + const children: Metadata[][] = metadata.children as Metadata[][]; + let { x, width } = metadata; + + const controlY = controlsY[0]; + + const elems: SVGElement[] = []; + + if (children != null) { + if (children.length !== 2) + throw new Error(`Invalid number of children found for classically-controlled gate: ${children.length}`); + + // Get SVG for gates controlled on 0 + const childrenZero: SVGElement = formatGates(children[0]); + childrenZero.setAttribute('class', 'gates-zero'); + elems.push(childrenZero); + + // Get SVG for gates controlled on 1 + const childrenOne: SVGElement = formatGates(children[1]); + childrenOne.setAttribute('class', 'gates-one'); + elems.push(childrenOne); + } + + // Draw control button and attached dashed line to dashed box + const controlCircleX: number = x + controlBtnRadius; + const controlCircle: SVGElement = _controlCircle(controlCircleX, controlY); + const lineY1: number = controlY + controlBtnRadius, + lineY2: number = controlY + classicalRegHeight / 2; + const vertLine: SVGElement = dashedLine(controlCircleX, lineY1, controlCircleX, lineY2, 'classical-line'); + x += controlBtnOffset; + const horLine: SVGElement = dashedLine(controlCircleX, lineY2, x, lineY2, 'classical-line'); + + width = width - controlBtnOffset + (padding - groupBoxPadding) * 2; + x += groupBoxPadding - padding; + const y: number = targetsY[0] - gateHeight / 2 - padding; + const height: number = targetsY[1] - targetsY[0] + gateHeight + padding * 2; + + // Draw dashed box around children gates + const box: SVGElement = dashedBox(x, y, width, height, 'classical-container'); + + elems.push(...[horLine, vertLine, controlCircle, box]); + + // Display controlled operation in initial "unknown" state + const attributes: { [attr: string]: string } = { + class: `classically-controlled-group classically-controlled-unknown`, + }; + if (dataAttributes != null) + Object.entries(dataAttributes).forEach(([attr, val]) => (attributes[`data-${attr}`] = val)); + + return group(elems, attributes); +}; + +/** + * Generates the SVG representation of the control circle on a classical register with interactivity support + * for toggling between bit values (unknown, 1, and 0). + * + * @param x x coord. + * @param y y coord. + * @param r Radius of circle. + * + * @returns SVG representation of control circle. + */ +const _controlCircle = (x: number, y: number, r: number = controlBtnRadius): SVGElement => + group([circle(x, y, r), text('?', x, y, labelFontSize)], { class: 'classically-controlled-btn' }); + +export { + formatGates, + _formatGate, + _createGate, + _zoomButton, + _measure, + _unitary, + _swap, + _controlledGate, + _groupedOperations, + _classicalControlled, +}; diff --git a/circuit_vis/src/formatters/inputFormatter.ts b/circuit_vis/src/formatters/inputFormatter.ts new file mode 100644 index 0000000000..e3acf98228 --- /dev/null +++ b/circuit_vis/src/formatters/inputFormatter.ts @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import { Qubit } from '../circuit'; +import { RegisterType, RegisterMap, RegisterMetadata } from '../register'; +import { leftPadding, startY, registerHeight, classicalRegHeight } from '../constants'; +import { group, text } from './formatUtils'; + +/** + * `formatInputs` takes in an array of Qubits and outputs the SVG string of formatted + * qubit wires and a mapping from register IDs to register metadata (for rendering). + * + * @param qubits List of declared qubits. + * + * @returns returns the SVG string of formatted qubit wires, a mapping from registers + * to y coord and total SVG height. + */ +const formatInputs = (qubits: Qubit[]): { qubitWires: SVGElement; registers: RegisterMap; svgHeight: number } => { + const qubitWires: SVGElement[] = []; + const registers: RegisterMap = {}; + + let currY: number = startY; + qubits.forEach(({ id, numChildren }) => { + // Add qubit wire to list of qubit wires + qubitWires.push(_qubitInput(currY)); + + // Create qubit register + registers[id] = { type: RegisterType.Qubit, y: currY }; + + // If there are no attached classical registers, increment y by fixed register height + if (numChildren == null || numChildren === 0) { + currY += registerHeight; + return; + } + + // Increment current height by classical register height for attached classical registers + currY += classicalRegHeight; + + // Add classical wires + registers[id].children = Array.from(Array(numChildren), () => { + const clsReg: RegisterMetadata = { type: RegisterType.Classical, y: currY }; + currY += classicalRegHeight; + return clsReg; + }); + }); + + return { + qubitWires: group(qubitWires), + registers, + svgHeight: currY, + }; +}; + +/** + * Generate the SVG text component for the input qubit register. + * + * @param y y coord of input wire to render in SVG. + * + * @returns SVG text component for the input register. + */ +const _qubitInput = (y: number): SVGElement => { + const el: SVGElement = text('|0⟩', leftPadding, y, 16); + el.setAttribute('text-anchor', 'start'); + el.setAttribute('dominant-baseline', 'middle'); + return el; +}; + +export { formatInputs, _qubitInput }; diff --git a/circuit_vis/src/formatters/registerFormatter.ts b/circuit_vis/src/formatters/registerFormatter.ts new file mode 100644 index 0000000000..3d9637c903 --- /dev/null +++ b/circuit_vis/src/formatters/registerFormatter.ts @@ -0,0 +1,104 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import { RegisterMap } from '../register'; +import { regLineStart } from '../constants'; +import { Metadata, GateType } from '../metadata'; +import { group, line, text } from './formatUtils'; + +/** + * Generate the SVG representation of the qubit register wires in `registers` and the classical wires + * stemming from each measurement gate. + * + * @param registers Map from register IDs to register metadata. + * @param measureGates Array of measurement gates metadata. + * @param endX End x coord. + * + * @returns SVG representation of register wires. + */ +const formatRegisters = (registers: RegisterMap, measureGates: Metadata[], endX: number): SVGElement => { + const formattedRegs: SVGElement[] = []; + // Render qubit wires + for (const qId in registers) { + formattedRegs.push(_qubitRegister(Number(qId), endX, registers[qId].y)); + } + // Render classical wires + measureGates.forEach(({ type, x, targetsY, controlsY }) => { + if (type !== GateType.Measure) return; + const gateY: number = controlsY[0]; + (targetsY as number[]).forEach((y) => { + formattedRegs.push(_classicalRegister(x, gateY, endX, y)); + }); + }); + return group(formattedRegs); +}; + +/** + * Generates the SVG representation of a classical register. + * + * @param startX Start x coord. + * @param gateY y coord of measurement gate. + * @param endX End x coord. + * @param wireY y coord of wire. + * + * @returns SVG representation of the given classical register. + */ +const _classicalRegister = (startX: number, gateY: number, endX: number, wireY: number): SVGElement => { + const wirePadding = 1; + // Draw vertical lines + const vLine1: SVGElement = line( + startX + wirePadding, + gateY, + startX + wirePadding, + wireY - wirePadding, + 'register-classical', + ); + const vLine2: SVGElement = line( + startX - wirePadding, + gateY, + startX - wirePadding, + wireY + wirePadding, + 'register-classical', + ); + + // Draw horizontal lines + const hLine1: SVGElement = line( + startX + wirePadding, + wireY - wirePadding, + endX, + wireY - wirePadding, + 'register-classical', + ); + const hLine2: SVGElement = line( + startX - wirePadding, + wireY + wirePadding, + endX, + wireY + wirePadding, + 'register-classical', + ); + + return group([vLine1, vLine2, hLine1, hLine2]); +}; + +/** + * Generates the SVG representation of a qubit register. + * + * @param qId Qubit register index. + * @param endX End x coord. + * @param y y coord of wire. + * @param labelOffset y offset for wire label. + * + * @returns SVG representation of the given qubit register. + */ +const _qubitRegister = (qId: number, endX: number, y: number, labelOffset = 16): SVGElement => { + const wire: SVGElement = line(regLineStart, y, endX, y); + + const label: SVGElement = text(`q${qId}`, regLineStart, y - labelOffset); + label.setAttribute('dominant-baseline', 'hanging'); + label.setAttribute('text-anchor', 'start'); + label.setAttribute('font-size', '75%'); + + return group([wire, label]); +}; + +export { formatRegisters, _classicalRegister, _qubitRegister }; diff --git a/circuit_vis/src/index.ts b/circuit_vis/src/index.ts new file mode 100644 index 0000000000..0a0402686c --- /dev/null +++ b/circuit_vis/src/index.ts @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import { Sqore } from './sqore'; +import { Circuit } from './circuit'; +import { StyleConfig } from './styles'; + +/** + * Render `circuit` into `container` at the specified layer depth. + * + * @param circuit Circuit to be visualized. + * @param container HTML element for rendering visualization into. + * @param style Custom visualization style. + * @param renderDepth Initial layer depth at which to render gates. + */ +export const draw = ( + circuit: Circuit, + container: HTMLElement, + style: StyleConfig | string = {}, + renderDepth = 0, +): void => { + const sqore = new Sqore(circuit, style); + sqore.draw(container, renderDepth); +}; + +export { STYLES } from './styles'; + +// Export types +export type { StyleConfig } from './styles'; +export type { Circuit, Qubit, Operation } from './circuit'; diff --git a/circuit_vis/src/metadata.ts b/circuit_vis/src/metadata.ts new file mode 100644 index 0000000000..827ac54676 --- /dev/null +++ b/circuit_vis/src/metadata.ts @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import { DataAttributes } from './circuit'; + +/** + * Enum for the various gate operations handled. + */ +export enum GateType { + /** Measurement gate. */ + Measure, + /** CNOT gate. */ + Cnot, + /** SWAP gate. */ + Swap, + /** X gate. */ + X, + /** Single/multi qubit unitary gate. */ + Unitary, + /** Single/multi controlled unitary gate. */ + ControlledUnitary, + /** Nested group of classically-controlled gates. */ + ClassicalControlled, + /** Group of nested gates */ + Group, + /** Invalid gate. */ + Invalid, +} + +/** + * Metadata used to store information pertaining to a given + * operation for rendering its corresponding SVG. + */ +export interface Metadata { + /** Gate type. */ + type: GateType; + /** Centre x coord for gate position. */ + x: number; + /** Array of y coords of control registers. */ + controlsY: number[]; + /** Array of y coords of target registers. + * For `GateType.Unitary` or `GateType.ControlledUnitary`, this is an array of groups of + * y coords, where each group represents a unitary box to be rendered separately. + */ + targetsY: (number | number[])[]; + /** Gate label. */ + label: string; + /** Gate arguments as string. */ + displayArgs?: string; + /** Gate width. */ + width: number; + /** Children operations as part of group. */ + children?: (Metadata | Metadata[])[]; + /** Custom data attributes to attach to gate element. */ + dataAttributes?: DataAttributes; +} diff --git a/circuit_vis/src/process.ts b/circuit_vis/src/process.ts new file mode 100644 index 0000000000..5c21f7f0fe --- /dev/null +++ b/circuit_vis/src/process.ts @@ -0,0 +1,453 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import { minGateWidth, startX, gatePadding, controlBtnOffset, groupBoxPadding } from './constants'; +import { Operation, ConditionalRender } from './circuit'; +import { Metadata, GateType } from './metadata'; +import { Register, RegisterMap, RegisterType } from './register'; +import { getGateWidth } from './utils'; + +/** + * Takes in a list of operations and maps them to `metadata` objects which + * contains information for formatting the corresponding SVG. + * + * @param operations Array of operations. + * @param registers Mapping from qubit IDs to register metadata. + * + * @returns An object containing `metadataList` (Array of Metadata objects) and + * `svgWidth` which is the width of the entire SVG. + */ +const processOperations = ( + operations: Operation[], + registers: RegisterMap, +): { metadataList: Metadata[]; svgWidth: number } => { + if (operations.length === 0) return { metadataList: [], svgWidth: startX }; + + // Group operations based on registers + const groupedOps: number[][] = _groupOperations(operations, registers); + + // Align operations on multiple registers + const alignedOps: (number | null)[][] = _alignOps(groupedOps); + + // Maintain widths of each column to account for variable-sized gates + const numColumns: number = Math.max(0, ...alignedOps.map((ops) => ops.length)); + const columnsWidths: number[] = new Array(numColumns).fill(minGateWidth); + + // Get classical registers and their starting column index + const classicalRegs: [number, Register][] = _getClassicalRegStart(operations, alignedOps); + + // Keep track of which ops are already seen to avoid duplicate rendering + const visited: { [opIdx: number]: boolean } = {}; + + // Map operation index to gate metadata for formatting later + const opsMetadata: Metadata[][] = alignedOps.map((regOps) => + regOps.map((opIdx, col) => { + let op: Operation | null = null; + + if (opIdx != null && !visited.hasOwnProperty(opIdx)) { + op = operations[opIdx]; + visited[opIdx] = true; + } + + const metadata: Metadata = _opToMetadata(op, registers); + + if (op != null && [GateType.Unitary, GateType.ControlledUnitary].includes(metadata.type)) { + // If gate is a unitary type, split targetsY into groups if there + // is a classical register between them for rendering + + // Get y coordinates of classical registers in the same column as this operation + const classicalRegY: number[] = classicalRegs + .filter(([regCol, _]) => regCol <= col) + .map(([_, reg]) => { + if (reg.cId == null) throw new Error('Could not find cId for classical register.'); + const { children } = registers[reg.qId]; + if (children == null) + throw new Error(`Failed to find classical registers for qubit ID ${reg.qId}.`); + return children[reg.cId].y; + }); + + metadata.targetsY = _splitTargetsY(op.targets, classicalRegY, registers); + } + + // Expand column size, if needed + if (metadata.width > columnsWidths[col]) { + columnsWidths[col] = metadata.width; + } + + return metadata; + }), + ); + + // Fill in x coord of each gate + const endX: number = _fillMetadataX(opsMetadata, columnsWidths); + + // Flatten operations and filter out invalid gates + const metadataList: Metadata[] = opsMetadata.flat().filter(({ type }) => type != GateType.Invalid); + + return { metadataList, svgWidth: endX }; +}; + +/** + * Group gates provided by operations into their respective registers. + * + * @param operations Array of operations. + * @param numRegs Total number of registers. + * + * @returns 2D array of indices where `groupedOps[i][j]` is the index of the operations + * at register `i` and column `j` (not yet aligned/padded). + */ +const _groupOperations = (operations: Operation[], registers: RegisterMap): number[][] => { + // NOTE: We get the max ID instead of just number of keys because there can be a qubit ID that + // isn't acted upon and thus does not show up as a key in registers. + const numRegs: number = Math.max(-1, ...Object.keys(registers).map(Number)) + 1; + const groupedOps: number[][] = Array.from(Array(numRegs), () => new Array(0)); + operations.forEach(({ targets, controls }, instrIdx) => { + const ctrls: Register[] = controls || []; + const qRegs: Register[] = [...ctrls, ...targets].filter( + ({ type }) => (type || RegisterType.Qubit) === RegisterType.Qubit, + ); + const qRegIdxList: number[] = qRegs.map(({ qId }) => qId); + const clsControls: Register[] = ctrls.filter( + ({ type }) => (type || RegisterType.Qubit) === RegisterType.Classical, + ); + const isClassicallyControlled: boolean = clsControls.length > 0; + if (!isClassicallyControlled && qRegs.length === 0) return; + // If operation is classically-controlled, pad all qubit registers. Otherwise, only pad + // the contiguous range of registers that it covers. + const minRegIdx: number = isClassicallyControlled ? 0 : Math.min(...qRegIdxList); + const maxRegIdx: number = isClassicallyControlled ? numRegs - 1 : Math.max(...qRegIdxList); + // Add operation also to registers that are in-between target registers + // so that other gates won't render in the middle. + for (let i = minRegIdx; i <= maxRegIdx; i++) { + groupedOps[i].push(instrIdx); + } + }); + return groupedOps; +}; + +/** + * Aligns operations by padding registers with `null`s to make sure that multiqubit + * gates are in the same column. + * e.g. ---[x]---[x]-- + * ----------|--- + * + * @param ops 2D array of operations. Each row represents a register + * and the operations acting on it (in-order). + * + * @returns 2D array of aligned operations padded with `null`s. + */ +const _alignOps = (ops: number[][]): (number | null)[][] => { + let maxNumOps: number = Math.max(0, ...ops.map((regOps) => regOps.length)); + let col = 0; + // Deep copy ops to be returned as paddedOps + const paddedOps: (number | null)[][] = JSON.parse(JSON.stringify(ops)); + while (col < maxNumOps) { + for (let regIdx = 0; regIdx < paddedOps.length; regIdx++) { + const reg: (number | null)[] = paddedOps[regIdx]; + if (reg.length <= col) continue; + + // Should never be null (nulls are only padded to previous columns) + const opIdx: number | null = reg[col]; + + // Get position of gate + const targetsPos: number[] = paddedOps.map((regOps) => regOps.indexOf(opIdx)); + const gatePos: number = Math.max(-1, ...targetsPos); + + // If current column is not desired gate position, pad with null + if (col < gatePos) { + paddedOps[regIdx].splice(col, 0, null); + maxNumOps = Math.max(maxNumOps, paddedOps[regIdx].length); + } + } + col++; + } + return paddedOps; +}; + +/** + * Retrieves the starting index of each classical register. + * + * @param ops Array of operations. + * @param idxList 2D array of aligned operation indices. + * + * @returns Array of classical register and their starting column indices in the form [[column, register]]. + */ +const _getClassicalRegStart = (ops: Operation[], idxList: (number | null)[][]): [number, Register][] => { + const clsRegs: [number, Register][] = []; + idxList.forEach((reg) => { + for (let col = 0; col < reg.length; col++) { + const opIdx: number | null = reg[col]; + if (opIdx != null && ops[opIdx].isMeasurement) { + const targetClsRegs: Register[] = ops[opIdx].targets.filter( + (reg) => reg.type === RegisterType.Classical, + ); + targetClsRegs.forEach((reg) => clsRegs.push([col, reg])); + } + } + }); + return clsRegs; +}; + +/** + * Maps operation to metadata (e.g. gate type, position, dimensions, text) + * required to render the image. + * + * @param op Operation to be mapped into metadata format. + * @param registers Array of registers. + * + * @returns Metadata representation of given operation. + */ +const _opToMetadata = (op: Operation | null, registers: RegisterMap): Metadata => { + const metadata: Metadata = { + type: GateType.Invalid, + x: 0, + controlsY: [], + targetsY: [], + label: '', + width: -1, + }; + + if (op == null) return metadata; + + const { + gate, + dataAttributes, + displayArgs, + isMeasurement, + isConditional, + isControlled, + isAdjoint, + controls, + targets, + children, + conditionalRender, + } = op; + + // Set y coords + metadata.controlsY = controls?.map((reg) => _getRegY(reg, registers)) || []; + metadata.targetsY = targets.map((reg) => _getRegY(reg, registers)); + + if (isConditional) { + // Classically-controlled operations + if (children == null || children.length == 0) + throw new Error('No children operations found for classically-controlled operation.'); + + // Gates to display when classical bit is 0. + const onZeroOps: Operation[] = children.filter((op) => op.conditionalRender !== ConditionalRender.OnOne); + let childrenInstrs = processOperations(onZeroOps, registers); + const zeroGates: Metadata[] = childrenInstrs.metadataList; + const zeroChildWidth: number = childrenInstrs.svgWidth; + + // Gates to display when classical bit is 1. + const onOneOps: Operation[] = children.filter((op) => op.conditionalRender !== ConditionalRender.OnZero); + childrenInstrs = processOperations(onOneOps, registers); + const oneGates: Metadata[] = childrenInstrs.metadataList; + const oneChildWidth: number = childrenInstrs.svgWidth; + + // Subtract startX (left-side) and 2*gatePadding (right-side) from nested child gates width + const width: number = Math.max(zeroChildWidth, oneChildWidth) - startX - gatePadding * 2; + + metadata.type = GateType.ClassicalControlled; + metadata.children = [zeroGates, oneGates]; + // Add additional width from control button and inner box padding for dashed box + metadata.width = width + controlBtnOffset + groupBoxPadding * 2; + + // Set targets to first and last quantum registers so we can render the surrounding box + // around all quantum registers. + const qubitsY: number[] = Object.values(registers).map(({ y }) => y); + if (qubitsY.length > 0) metadata.targetsY = [Math.min(...qubitsY), Math.max(...qubitsY)]; + } else if (conditionalRender == ConditionalRender.AsGroup && (children?.length || 0) > 0) { + const childrenInstrs = processOperations(children as Operation[], registers); + metadata.type = GateType.Group; + metadata.children = childrenInstrs.metadataList; + // _zoomButton function in gateFormatter.ts relies on + // 'expanded' attribute to render zoom button + metadata.dataAttributes = { expanded: 'true' }; + // Subtract startX (left-side) and add inner box padding (minus nested gate padding) for dashed box + metadata.width = childrenInstrs.svgWidth - startX + (groupBoxPadding - gatePadding) * 2; + } else if (isMeasurement) { + metadata.type = GateType.Measure; + } else if (gate === 'SWAP') { + metadata.type = GateType.Swap; + } else if (isControlled) { + metadata.type = gate === 'X' ? GateType.Cnot : GateType.ControlledUnitary; + metadata.label = gate; + } else if (gate === 'X') { + metadata.type = GateType.X; + metadata.label = gate; + } else { + // Any other gate treated as a simple unitary gate + metadata.type = GateType.Unitary; + metadata.label = gate; + } + + // If adjoint, add ' to the end of gate label + if (isAdjoint && metadata.label.length > 0) metadata.label += "'"; + + // If gate has extra arguments, display them + if (displayArgs != null) metadata.displayArgs = displayArgs; + + // Set gate width + metadata.width = getGateWidth(metadata); + + // Extend existing data attributes with user-provided data attributes + if (dataAttributes != null) metadata.dataAttributes = { ...metadata.dataAttributes, ...dataAttributes }; + + return metadata; +}; + +/** + * Compute the y coord of a given register. + * + * @param reg Register to compute y coord of. + * @param registers Map of qubit IDs to RegisterMetadata. + * + * @returns The y coord of give register. + */ +const _getRegY = (reg: Register, registers: RegisterMap): number => { + const { type, qId, cId } = reg; + if (!registers.hasOwnProperty(qId)) throw new Error(`ERROR: Qubit register with ID ${qId} not found.`); + const { y, children } = registers[qId]; + switch (type) { + case undefined: + case RegisterType.Qubit: + return y; + case RegisterType.Classical: + if (children == null) throw new Error(`ERROR: No classical registers found for qubit ID ${qId}.`); + if (cId == null) + throw new Error(`ERROR: No ID defined for classical register associated with qubit ID ${qId}.`); + if (children.length <= cId) + throw new Error( + `ERROR: Classical register ID ${cId} invalid for qubit ID ${qId} with ${children.length} classical register(s).`, + ); + return children[cId].y; + default: + throw new Error(`ERROR: Unknown register type ${type}.`); + } +}; + +/** + * Splits `targets` if non-adjacent or intersected by classical registers. + * + * @param targets Target qubit registers. + * @param classicalRegY y coords of classical registers overlapping current column. + * @param registers Mapping from register qubit IDs to register metadata. + * + * @returns Groups of target qubit y coords. + */ +const _splitTargetsY = (targets: Register[], classicalRegY: number[], registers: RegisterMap): number[][] => { + if (targets.length === 0) return []; + + // Get qIds sorted by ascending y value + const orderedQIds: number[] = Object.keys(registers).map(Number); + orderedQIds.sort((a, b) => registers[a].y - registers[b].y); + const qIdPosition: { [qId: number]: number } = {}; + orderedQIds.forEach((qId, i) => (qIdPosition[qId] = i)); + + // Sort targets and classicalRegY by ascending y value + targets = targets.slice(); + targets.sort((a, b) => { + const posDiff: number = qIdPosition[a.qId] - qIdPosition[b.qId]; + if (posDiff === 0 && a.cId != null && b.cId != null) return a.cId - b.cId; + else return posDiff; + }); + classicalRegY = classicalRegY.slice(); + classicalRegY.sort((a, b) => a - b); + + let prevPos = 0; + let prevY = 0; + + return targets.reduce((groups: number[][], target: Register) => { + const y = _getRegY(target, registers); + const pos = qIdPosition[target.qId]; + + // Split into new group if one of the following holds: + // 1. First target register + // 2. Non-adjacent qubit registers + // 3. There is a classical register between current and previous register + if (groups.length === 0 || pos > prevPos + 1 || (classicalRegY[0] > prevY && classicalRegY[0] < y)) + groups.push([y]); + else groups[groups.length - 1].push(y); + + prevPos = pos; + prevY = y; + + // Remove classical registers that are higher than current y + while (classicalRegY.length > 0 && classicalRegY[0] <= y) classicalRegY.shift(); + + return groups; + }, []); +}; + +/** + * Updates the x coord of each metadata in the given 2D array of metadata and returns rightmost x coord. + * + * @param opsMetadata 2D array of metadata. + * @param columnWidths Array of column widths. + * + * @returns Rightmost x coord. + */ +const _fillMetadataX = (opsMetadata: Metadata[][], columnWidths: number[]): number => { + let currX: number = startX; + + const colStartX: number[] = columnWidths.map((width) => { + const x: number = currX; + currX += width + gatePadding * 2; + return x; + }); + + const endX: number = currX; + + opsMetadata.forEach((regOps) => + regOps.forEach((metadata, col) => { + const x = colStartX[col]; + switch (metadata.type) { + case GateType.ClassicalControlled: + case GateType.Group: + // Subtract startX offset from nested gates and add offset and padding + let offset: number = x - startX + groupBoxPadding; + if (metadata.type === GateType.ClassicalControlled) offset += controlBtnOffset; + + // Offset each x coord in children gates + _offsetChildrenX(metadata.children, offset); + + // We don't use the centre x coord because we only care about the rightmost x for + // rendering the box around the group of nested gates + metadata.x = x; + break; + + default: + metadata.x = x + columnWidths[col] / 2; + break; + } + }), + ); + + return endX; +}; + +/** + * Offset x coords of nested children operations. + * + * @param children 2D array of children metadata. + * @param offset x coord offset. + */ +const _offsetChildrenX = (children: (Metadata | Metadata[])[] | undefined, offset: number): void => { + if (children == null) return; + children.flat().forEach((child) => { + child.x += offset; + _offsetChildrenX(child.children, offset); + }); +}; + +export { + processOperations, + _groupOperations, + _alignOps, + _getClassicalRegStart, + _opToMetadata, + _getRegY, + _splitTargetsY, + _fillMetadataX, + _offsetChildrenX, +}; diff --git a/circuit_vis/src/register.ts b/circuit_vis/src/register.ts new file mode 100644 index 0000000000..cdc28dab91 --- /dev/null +++ b/circuit_vis/src/register.ts @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +/** + * Type of register. + */ +export enum RegisterType { + Qubit, + Classical, +} + +/** + * Represents a register resource. + */ +export interface Register { + /** Type of register. If missing defaults to Qubit. */ + type?: RegisterType; + /** Qubit register ID. */ + qId: number; + /** Classical register ID (if classical register). */ + cId?: number; +} + +/** + * Metadata for qubit register. + */ +export interface RegisterMetadata { + /** Type of register. */ + type: RegisterType; + /** y coord of register */ + y: number; + /** Nested classical registers attached to quantum register. */ + children?: RegisterMetadata[]; +} + +/** + * Mapping from qubit IDs to their register metadata. + */ +export interface RegisterMap { + [id: number]: RegisterMetadata; +} diff --git a/circuit_vis/src/sqore.ts b/circuit_vis/src/sqore.ts new file mode 100644 index 0000000000..c20ba65c75 --- /dev/null +++ b/circuit_vis/src/sqore.ts @@ -0,0 +1,351 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import { formatInputs } from './formatters/inputFormatter'; +import { formatGates } from './formatters/gateFormatter'; +import { formatRegisters } from './formatters/registerFormatter'; +import { processOperations } from './process'; +import { ConditionalRender, Circuit, Operation } from './circuit'; +import { Metadata, GateType } from './metadata'; +import { StyleConfig, style, STYLES } from './styles'; +import { createUUID } from './utils'; +import { svgNS } from './constants'; + +/** + * Contains metadata for visualization. + */ +interface ComposedSqore { + /** Width of visualization. */ + width: number; + /** Height of visualization. */ + height: number; + /** SVG elements the make up the visualization. */ + elements: SVGElement[]; +} + +/** + * Defines the mapping of unique ID to each operation. Used for enabling + * interactivity. + */ +type GateRegistry = { + [id: string]: Operation; +}; + +/** + * Entrypoint class for rendering circuit visualizations. + */ +export class Sqore { + circuit: Circuit; + style: StyleConfig = {}; + gateRegistry: GateRegistry = {}; + + /** + * Initializes Sqore object with custom styles. + * + * @param circuit Circuit to be visualized. + * @param style Custom visualization style. + */ + constructor(circuit: Circuit, style: StyleConfig | string = {}) { + this.circuit = circuit; + this.style = this.getStyle(style); + } + + /** + * Render circuit into `container` at the specified layer depth. + * + * @param container HTML element for rendering visualization into. + * @param renderDepth Initial layer depth at which to render gates. + */ + draw(container: HTMLElement, renderDepth = 0): void { + // Inject into container + if (container == null) throw new Error(`Container not provided.`); + + // Create copy of circuit to prevent mutation + const circuit: Circuit = JSON.parse(JSON.stringify(this.circuit)); + + // Assign unique IDs to each operation + circuit.operations.forEach((op, i) => this.fillGateRegistry(op, i.toString())); + + // Render operations at starting at given depth + circuit.operations = this.selectOpsAtDepth(circuit.operations, renderDepth); + + // If only one top-level operation, expand automatically: + if ( + circuit.operations.length == 1 && + circuit.operations[0].dataAttributes != null && + circuit.operations[0].dataAttributes.hasOwnProperty('id') + ) { + const id: string = circuit.operations[0].dataAttributes['id']; + this.expandOperation(circuit.operations, id); + } + + this.renderCircuit(container, circuit); + } + + /** + * Retrieve style for visualization. + * + * @param style Custom style or style name. + * + * @returns Custom style. + */ + private getStyle(style: StyleConfig | string = {}): StyleConfig { + if (typeof style === 'string' || style instanceof String) { + const styleName: string = style as string; + if (!STYLES.hasOwnProperty(styleName)) { + console.error(`No style ${styleName} found in STYLES.`); + return {}; + } + style = STYLES[styleName]; + } + return style; + } + + /** + * Render circuit into `container`. + * + * @param container HTML element for rendering visualization into. + * @param circuit Circuit object to be rendered. + */ + private renderCircuit(container: HTMLElement, circuit: Circuit): void { + // Create visualization components + const composedSqore: ComposedSqore = this.compose(circuit); + const svg: SVGElement = this.generateSvg(composedSqore); + container.innerHTML = ''; + container.appendChild(svg); + this.addGateClickHandlers(container, circuit); + } + + /** + * Generates the components required for visualization. + * + * @param circuit Circuit to be visualized. + * + * @returns `ComposedSqore` object containing metadata for visualization. + */ + private compose(circuit: Circuit): ComposedSqore { + const add = (acc: Metadata[], gate: Metadata | Metadata[]): void => { + if (Array.isArray(gate)) { + gate.forEach((g) => add(acc, g)); + } else { + acc.push(gate); + gate.children?.forEach((g) => add(acc, g)); + } + }; + + const flatten = (gates: Metadata[]): Metadata[] => { + const result: Metadata[] = []; + add(result, gates); + return result; + }; + + const { qubits, operations } = circuit; + const { qubitWires, registers, svgHeight } = formatInputs(qubits); + const { metadataList, svgWidth } = processOperations(operations, registers); + const formattedGates: SVGElement = formatGates(metadataList); + const measureGates: Metadata[] = flatten(metadataList).filter(({ type }) => type === GateType.Measure); + const formattedRegs: SVGElement = formatRegisters(registers, measureGates, svgWidth); + + const composedSqore: ComposedSqore = { + width: svgWidth, + height: svgHeight, + elements: [qubitWires, formattedRegs, formattedGates], + }; + return composedSqore; + } + + /** + * Generates visualization of `composedSqore` as an SVG. + * + * @param composedSqore ComposedSqore to be visualized. + * + * @returns SVG representation of circuit visualization. + */ + private generateSvg(composedSqore: ComposedSqore): SVGElement { + const { width, height, elements } = composedSqore; + const uuid: string = createUUID(); + + const svg: SVGElement = document.createElementNS(svgNS, 'svg'); + svg.setAttribute('id', uuid); + svg.setAttribute('class', 'qviz'); + svg.setAttribute('width', width.toString()); + svg.setAttribute('height', height.toString()); + svg.style.setProperty('max-width', 'fit-content'); + + // Add styles + const css = document.createElement('style'); + css.innerHTML = style(this.style); + svg.appendChild(css); + + // Add body elements + elements.forEach((element: SVGElement) => svg.appendChild(element)); + + return svg; + } + + /** + * Depth-first traversal to assign unique ID to `operation`. + * The operation is assigned the id `id` and its `i`th child is recursively given + * the id `${id}-${i}`. + * + * @param operation Operation to be assigned. + * @param id: ID to assign to `operation`. + * + */ + private fillGateRegistry(operation: Operation, id: string): void { + if (operation.dataAttributes == null) operation.dataAttributes = {}; + operation.dataAttributes['id'] = id; + // By default, operations cannot be zoomed-out + operation.dataAttributes['zoom-out'] = 'false'; + this.gateRegistry[id] = operation; + operation.children?.forEach((childOp, i) => { + this.fillGateRegistry(childOp, `${id}-${i}`); + if (childOp.dataAttributes == null) childOp.dataAttributes = {}; + // Children operations can be zoomed out + childOp.dataAttributes['zoom-out'] = 'true'; + }); + // Composite operations can be zoomed in + operation.dataAttributes['zoom-in'] = (operation.children != null).toString(); + } + + /** + * Pick out operations that are at or below `renderDepth`. + * + * @param operations List of circuit operations. + * @param renderDepth Initial layer depth at which to render gates. + * + * @returns List of operations at or below specifed depth. + */ + private selectOpsAtDepth(operations: Operation[], renderDepth: number): Operation[] { + if (renderDepth < 0) throw new Error(`Invalid renderDepth of ${renderDepth}. Needs to be >= 0.`); + if (renderDepth === 0) return operations; + return operations + .map((op) => (op.children != null ? this.selectOpsAtDepth(op.children, renderDepth - 1) : op)) + .flat(); + } + + /** + * Add interactive click handlers to circuit HTML elements. + * + * @param container HTML element containing visualized circuit. + * @param circuit Circuit to be visualized. + * + */ + private addGateClickHandlers(container: HTMLElement, circuit: Circuit): void { + this.addClassicalControlHandlers(container); + this.addZoomHandlers(container, circuit); + } + + /** + * Add interactive click handlers for classically-controlled operations. + * + * @param container HTML element containing visualized circuit. + * + */ + private addClassicalControlHandlers(container: HTMLElement): void { + container.querySelectorAll('.classically-controlled-btn').forEach((btn) => { + // Zoom in on clicked gate + btn.addEventListener('click', (evt: Event) => { + const textSvg = btn.querySelector('text'); + const group = btn.parentElement; + if (textSvg == null || group == null) return; + + const currValue = textSvg.firstChild?.nodeValue; + const zeroGates = group?.querySelector('.gates-zero'); + const oneGates = group?.querySelector('.gates-one'); + switch (currValue) { + case '?': + textSvg.childNodes[0].nodeValue = '1'; + group.classList.remove('classically-controlled-unknown'); + group.classList.remove('classically-controlled-zero'); + group.classList.add('classically-controlled-one'); + zeroGates?.classList.add('hidden'); + oneGates?.classList.remove('hidden'); + break; + case '1': + textSvg.childNodes[0].nodeValue = '0'; + group.classList.remove('classically-controlled-unknown'); + group.classList.add('classically-controlled-zero'); + group.classList.remove('classically-controlled-one'); + zeroGates?.classList.remove('hidden'); + oneGates?.classList.add('hidden'); + break; + case '0': + textSvg.childNodes[0].nodeValue = '?'; + group.classList.add('classically-controlled-unknown'); + group.classList.remove('classically-controlled-zero'); + group.classList.remove('classically-controlled-one'); + zeroGates?.classList.remove('hidden'); + oneGates?.classList.remove('hidden'); + break; + } + evt.stopPropagation(); + }); + }); + } + + /** + * Add interactive click handlers for zoom-in/out functionality. + * + * @param container HTML element containing visualized circuit. + * @param circuit Circuit to be visualized. + * + */ + private addZoomHandlers(container: HTMLElement, circuit: Circuit): void { + container.querySelectorAll('.gate .gate-control').forEach((ctrl) => { + // Zoom in on clicked gate + ctrl.addEventListener('click', (ev: Event) => { + const gateId: string | null | undefined = ctrl.parentElement?.getAttribute('data-id'); + if (typeof gateId == 'string') { + if (ctrl.classList.contains('gate-collapse')) { + this.collapseOperation(circuit.operations, gateId); + } else if (ctrl.classList.contains('gate-expand')) { + this.expandOperation(circuit.operations, gateId); + } + this.renderCircuit(container, circuit); + + ev.stopPropagation(); + } + }); + }); + } + + /** + * Expand selected operation for zoom-in interaction. + * + * @param operations List of circuit operations. + * @param id ID of operation to expand. + * + */ + private expandOperation(operations: Operation[], id: string): void { + operations.forEach((op) => { + if (op.conditionalRender === ConditionalRender.AsGroup) this.expandOperation(op.children || [], id); + if (op.dataAttributes == null) return op; + const opId: string = op.dataAttributes['id']; + if (opId === id && op.children != null) { + op.conditionalRender = ConditionalRender.AsGroup; + op.dataAttributes['expanded'] = 'true'; + } + }); + } + + /** + * Collapse selected operation for zoom-out interaction. + * + * @param operations List of circuit operations. + * @param id ID of operation to collapse. + * + */ + private collapseOperation(operations: Operation[], parentId: string): void { + operations.forEach((op) => { + if (op.conditionalRender === ConditionalRender.AsGroup) this.collapseOperation(op.children || [], parentId); + if (op.dataAttributes == null) return op; + const opId: string = op.dataAttributes['id']; + // Collapse parent gate and its children + if (opId.startsWith(parentId)) { + op.conditionalRender = ConditionalRender.Always; + delete op.dataAttributes['expanded']; + } + }); + } +} diff --git a/circuit_vis/src/styles.ts b/circuit_vis/src/styles.ts new file mode 100644 index 0000000000..491d563eb2 --- /dev/null +++ b/circuit_vis/src/styles.ts @@ -0,0 +1,236 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +/** + * Provides configuration for CSS styles of visualization. + */ +export interface StyleConfig { + /** Line stroke style. */ + lineStroke?: string; + /** Line width. */ + lineWidth?: number; + /** Text colour. */ + textColour?: string; + /** Single qubit unitary fill colour. */ + unitary?: string; + /** Oplus circle fill colour. */ + oplus?: string; + /** Measurement gate fill colour. */ + measure?: string; + /** Measurement unknown primary colour. */ + classicalUnknown?: string; + /** Measurement zero primary colour. */ + classicalZero?: string; + /** Measurement one primary colour. */ + classicalOne?: string; + /** Measurement zero text colour */ + classicalZeroText?: string; + /** Measurement one text colour */ + classicalOneText?: string; +} + +const defaultStyle: StyleConfig = { + lineStroke: '#000000', + lineWidth: 1, + textColour: '#000000', + unitary: '#D9F1FA', + oplus: '#FFFFFF', + measure: '#FFDE86', + classicalUnknown: '#E5E5E5', + classicalZero: '#C40000', + classicalOne: '#4059BD', + classicalZeroText: '#FFFFFF', + classicalOneText: '#FFFFFF', +}; + +const blackAndWhiteStyle: StyleConfig = { + lineStroke: '#000000', + lineWidth: 1, + textColour: '#000000', + unitary: '#FFFFFF', + oplus: '#FFFFFF', + measure: '#FFFFFF', + classicalUnknown: '#FFFFFF', + classicalZero: '#000000', + classicalOne: '#000000', + classicalZeroText: '#FFFFFF', + classicalOneText: '#FFFFFF', +}; + +const invertedStyle: StyleConfig = { + lineStroke: '#FFFFFF', + lineWidth: 1, + textColour: '#FFFFFF', + unitary: '#000000', + oplus: '#000000', + measure: '#000000', + classicalUnknown: '#000000', + classicalZero: '#FFFFFF', + classicalOne: '#FFFFFF', + classicalZeroText: '#000000', + classicalOneText: '#000000', +}; + +/** + * Set of default styles. + */ +export const STYLES: { [name: string]: StyleConfig } = { + /** Default style with coloured gates. */ + Default: defaultStyle, + /** Black and white style. */ + BlackAndWhite: blackAndWhiteStyle, + /** Inverted black and white style (for black backgrounds). */ + Inverted: invertedStyle, +}; + +/** + * CSS style script to be injected into visualization SVG. + * + * @param customStyle Custom style configuration. + * + * @returns String containing CSS style script. + */ +export const style = (customStyle: StyleConfig = {}): string => { + const styleConfig = { ...defaultStyle, ...customStyle }; + + return `${_defaultGates(styleConfig)} + ${_classicallyControlledGates(styleConfig)} + ${_expandCollapse}`; +}; + +const _defaultGates = (styleConfig: StyleConfig): string => ` + line, + circle, + rect { + stroke: ${styleConfig.lineStroke}; + stroke-width: ${styleConfig.lineWidth}; + } + text { + fill: ${styleConfig.textColour}; + dominant-baseline: middle; + text-anchor: middle; + font-family: Arial; + } + .control-dot { + fill: ${styleConfig.lineStroke}; + } + .oplus line, .oplus circle { + fill: ${styleConfig.oplus}; + stroke-width: 2; + } + .gate-unitary { + fill: ${styleConfig.unitary}; + } + .gate-measure { + fill: ${styleConfig.measure}; + } + rect.gate-swap { + fill: transparent; + stroke: transparent; + } + .arc-measure { + stroke: ${styleConfig.lineStroke}; + fill: none; + stroke-width: ${styleConfig.lineWidth}; + } + .register-classical { + stroke-width: ${(styleConfig.lineWidth || 0) / 2}; + }`; + +const _classicallyControlledGates = (styleConfig: StyleConfig): string => { + const gateOutline = ` + .classically-controlled-one .classical-container, + .classically-controlled-one .classical-line { + stroke: ${styleConfig.classicalOne}; + stroke-width: ${(styleConfig.lineWidth || 0) + 0.3}; + fill: ${styleConfig.classicalOne}; + fill-opacity: 0.1; + } + .classically-controlled-zero .classical-container, + .classically-controlled-zero .classical-line { + stroke: ${styleConfig.classicalZero}; + stroke-width: ${(styleConfig.lineWidth || 0) + 0.3}; + fill: ${styleConfig.classicalZero}; + fill-opacity: 0.1; + }`; + const controlBtn = ` + .classically-controlled-btn { + cursor: pointer; + } + .classically-controlled-unknown .classically-controlled-btn { + fill: ${styleConfig.classicalUnknown}; + } + .classically-controlled-one .classically-controlled-btn { + fill: ${styleConfig.classicalOne}; + } + .classically-controlled-zero .classically-controlled-btn { + fill: ${styleConfig.classicalZero}; + }`; + + const controlBtnText = ` + .classically-controlled-btn text { + dominant-baseline: middle; + text-anchor: middle; + stroke: none; + font-family: Arial; + } + .classically-controlled-unknown .classically-controlled-btn text { + fill: ${styleConfig.textColour}; + } + .classically-controlled-one .classically-controlled-btn text { + fill: ${styleConfig.classicalOneText}; + } + .classically-controlled-zero .classically-controlled-btn text { + fill: ${styleConfig.classicalZeroText}; + }`; + + return ` + .hidden { + display: none; + } + .classically-controlled-unknown { + opacity: 0.25; + } + + ${gateOutline} + ${controlBtn} + ${controlBtnText}`; +}; + +const _expandCollapse = ` + .qviz .gate-collapse, + .qviz .gate-expand { + opacity: 0; + transition: opacity 1s; + } + + .qviz:hover .gate-collapse, + .qviz:hover .gate-expand { + visibility: visible; + opacity: 0.2; + transition: visibility 1s; + transition: opacity 1s; + } + + .gate-expand, .gate-collapse { + cursor: pointer; + } + + .gate-collapse circle, + .gate-expand circle { + fill: white; + stroke-width: 2px; + stroke: black; + } + .gate-collapse path, + .gate-expand path { + stroke-width: 4px; + stroke: black; + } + + .gate:hover > .gate-collapse, + .gate:hover > .gate-expand { + visibility: visible; + opacity: 1; + transition: opacity 1s; + }`; diff --git a/circuit_vis/src/utils.ts b/circuit_vis/src/utils.ts new file mode 100644 index 0000000000..6a7e6c7d9f --- /dev/null +++ b/circuit_vis/src/utils.ts @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import { Metadata, GateType } from './metadata'; +import { minGateWidth, labelPadding, labelFontSize, argsFontSize } from './constants'; + +/** + * Generate a UUID using `Math.random`. + * Note: this implementation came from https://stackoverflow.com/questions/105034/how-to-create-guid-uuid + * and is not cryptographically secure but works for our use case. + * + * @returns UUID string. + */ +const createUUID = (): string => + 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + const r = (Math.random() * 16) | 0, + v = c == 'x' ? r : (r & 0x3) | 0x8; + return v.toString(16); + }); + +/** + * Calculate the width of a gate, given its metadata. + * + * @param metadata Metadata of a given gate. + * + * @returns Width of given gate (in pixels). + */ +const getGateWidth = ({ type, label, displayArgs, width }: Metadata): number => { + if (width > 0) return width; + + switch (type) { + case GateType.Measure: + case GateType.Cnot: + case GateType.Swap: + return minGateWidth; + default: + const labelWidth = _getStringWidth(label); + const argsWidth = displayArgs != null ? _getStringWidth(displayArgs, argsFontSize) : 0; + const textWidth = Math.max(labelWidth, argsWidth) + labelPadding * 2; + return Math.max(minGateWidth, textWidth); + } +}; + +/** + * Get the width of a string with font-size `fontSize` and font-family Arial. + * + * @param text Input string. + * @param fontSize Font size of `text`. + * + * @returns Pixel width of given string. + */ +const _getStringWidth = (text: string, fontSize: number = labelFontSize): number => { + const canvas: HTMLCanvasElement = document.createElement('canvas'); + const context: CanvasRenderingContext2D | null = canvas.getContext('2d'); + if (context == null) throw new Error('Null canvas'); + + context.font = `${fontSize}px Arial`; + const metrics: TextMetrics = context.measureText(text); + return metrics.width; +}; + +export { createUUID, getGateWidth, _getStringWidth }; diff --git a/circuit_vis/tsconfig.json b/circuit_vis/tsconfig.json new file mode 100644 index 0000000000..47f4409706 --- /dev/null +++ b/circuit_vis/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "commonjs", + "lib": [ + "DOM", + "ES2019", + ], + "declaration": true, + "strict": true, + "outDir": "lib", + "skipLibCheck": true + }, + "include": [ + "src/**/*" + ] +} diff --git a/circuit_vis/webpack.config.js b/circuit_vis/webpack.config.js new file mode 100644 index 0000000000..d712e5ca04 --- /dev/null +++ b/circuit_vis/webpack.config.js @@ -0,0 +1,71 @@ +const path = require('path'); +const TerserPlugin = require('terser-webpack-plugin'); + +const PATHS = { + entryPoint: path.resolve(__dirname, 'src/index.ts'), + bundles: path.resolve(__dirname, 'dist'), +}; + +const config = { + // Enables production mode built-in optimizations + mode: 'production', + // These are the entry point of our library. We tell webpack to use + // the name we assign later, when creating the bundle. We also use + // the name to filter the second entry point for applying code + // minification via UglifyJS + entry: { + qviz: [PATHS.entryPoint], + 'qviz.min': [PATHS.entryPoint], + }, + // The output defines how and where we want the bundles. The special + // value `[name]` in `filename` tell Webpack to use the name we defined above. + // The bundled script will be available as a global variable `qviz`. + output: { + path: PATHS.bundles, + filename: '[name].js', + library: 'qviz', + libraryTarget: 'umd', + }, + // Add resolve for `tsx` and `ts` files, otherwise Webpack would + // only look for common JavaScript file extension (.js) + resolve: { + extensions: ['.ts', '.tsx', '.js'], + }, + // Activate source maps for the bundles in order to preserve the original + // source when the user debugs the application + devtool: 'source-map', + optimization: { + // Apply minification only on the second bundle by + // using a RegEx on the name, which must end with `.min.js` + minimize: true, + minimizer: [ + new TerserPlugin({ + sourceMap: true, + include: /\.min\.js$/, + }), + ], + }, + module: { + // Webpack doesn't understand TypeScript files and a loader is needed. + // `node_modules` folder is excluded in order to prevent problems with + // the library dependencies, as well as `__tests__` folders that + // contain the tests for the library + rules: [ + { + test: /\.tsx?$/, + exclude: /node_modules/, + use: [ + { + loader: 'ts-loader', + options: { + // Speeds up compilation and does not build *.d.ts files + transpileOnly: true, + }, + }, + ], + }, + ], + }, +}; + +module.exports = config; From a9c0faa236b16a5ab60721fc02c3fb06cd0fb3fe Mon Sep 17 00:00:00 2001 From: Mine Starks <16928427+minestarks@users.noreply.github.com> Date: Thu, 30 May 2024 20:51:51 +0000 Subject: [PATCH 2/5] (circuits) prettier circuit_vis --- circuit_vis/.eslintrc.cjs | 42 +- circuit_vis/.prettierrc.js | 30 +- circuit_vis/README.md | 39 +- circuit_vis/SECURITY.md | 16 +- circuit_vis/__tests__/gateFormatter.test.ts | 1979 +++--- circuit_vis/__tests__/inputFormatter.test.ts | 176 +- circuit_vis/__tests__/process.test.ts | 5438 +++++++++-------- .../__tests__/registerFormatter.test.ts | 356 +- circuit_vis/__tests__/utils.test.ts | 118 +- circuit_vis/example/circuits.js | 3141 +++++----- circuit_vis/example/index.html | 91 +- circuit_vis/example/script.js | 40 +- circuit_vis/jest.config.js | 12 +- circuit_vis/src/circuit.ts | 78 +- circuit_vis/src/constants.ts | 2 +- circuit_vis/src/formatters/formatUtils.ts | 155 +- circuit_vis/src/formatters/gateFormatter.ts | 634 +- circuit_vis/src/formatters/inputFormatter.ts | 80 +- .../src/formatters/registerFormatter.ts | 130 +- circuit_vis/src/index.ts | 24 +- circuit_vis/src/metadata.ts | 80 +- circuit_vis/src/process.ts | 756 ++- circuit_vis/src/register.ts | 30 +- circuit_vis/src/sqore.ts | 625 +- circuit_vis/src/styles.ts | 134 +- circuit_vis/src/utils.ts | 68 +- circuit_vis/tsconfig.json | 25 +- circuit_vis/webpack.config.js | 122 +- 28 files changed, 7531 insertions(+), 6890 deletions(-) diff --git a/circuit_vis/.eslintrc.cjs b/circuit_vis/.eslintrc.cjs index 23abbbdca7..6ec2ace09b 100644 --- a/circuit_vis/.eslintrc.cjs +++ b/circuit_vis/.eslintrc.cjs @@ -1,23 +1,23 @@ module.exports = { - parser: '@typescript-eslint/parser', // Specifies the ESLint parser - parserOptions: { - ecmaVersion: 2019, // Allows for the parsing of modern ECMAScript features - sourceType: 'module', // Allows for the use of imports - }, - extends: [ - 'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin - 'prettier/@typescript-eslint', // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier - 'plugin:prettier/recommended', // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. - ], - plugins: ['jest'], - rules: { - // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs - // e.g. "@typescript-eslint/explicit-function-return-type": "off", - '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '_' }], - 'jest/no-disabled-tests': 'warn', - 'jest/no-focused-tests': 'error', - 'jest/no-identical-title': 'error', - 'jest/prefer-to-have-length': 'warn', - 'jest/valid-expect': 'error', - }, + parser: "@typescript-eslint/parser", // Specifies the ESLint parser + parserOptions: { + ecmaVersion: 2019, // Allows for the parsing of modern ECMAScript features + sourceType: "module", // Allows for the use of imports + }, + extends: [ + "plugin:@typescript-eslint/recommended", // Uses the recommended rules from the @typescript-eslint/eslint-plugin + "prettier/@typescript-eslint", // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier + "plugin:prettier/recommended", // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. + ], + plugins: ["jest"], + rules: { + // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs + // e.g. "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "_" }], + "jest/no-disabled-tests": "warn", + "jest/no-focused-tests": "error", + "jest/no-identical-title": "error", + "jest/prefer-to-have-length": "warn", + "jest/valid-expect": "error", + }, }; diff --git a/circuit_vis/.prettierrc.js b/circuit_vis/.prettierrc.js index 9d3becd4b7..7780e14a1e 100644 --- a/circuit_vis/.prettierrc.js +++ b/circuit_vis/.prettierrc.js @@ -1,17 +1,17 @@ module.exports = { - semi: true, - trailingComma: 'all', - singleQuote: true, - endOfLine: 'lf', - printWidth: 120, - tabWidth: 4, - parser: 'typescript', - overrides: [ - { - files: ['*.md', '*.json', '*.yml', '*.yaml'], - options: { - tabWidth: 2, - }, - }, - ], + semi: true, + trailingComma: "all", + singleQuote: true, + endOfLine: "lf", + printWidth: 120, + tabWidth: 4, + parser: "typescript", + overrides: [ + { + files: ["*.md", "*.json", "*.yml", "*.yaml"], + options: { + tabWidth: 2, + }, + }, + ], }; diff --git a/circuit_vis/README.md b/circuit_vis/README.md index f3e9cd2222..9a0d5dd57c 100644 --- a/circuit_vis/README.md +++ b/circuit_vis/README.md @@ -1,4 +1,5 @@ # quantum-viz.js + [![Licensed under the MIT License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE.txt) [![PR's Welcome](https://img.shields.io/badge/PRs%20-welcome-brightgreen.svg)](CONTRIBUTING.md) [![Build Status](https://github.com/microsoft/quantum-viz.js/actions/workflows/main.yml/badge.svg)](https://github.com/microsoft/quantum-viz.js/actions) @@ -11,34 +12,41 @@ **quantum-viz.js** (or **qviz**) is a configurable tool for rendering quantum circuits. With the increasing demand for quantum libraries and educational tools, quantum circuits provide an intuitive way to visualize and understand quantum algorithms. quantum-viz.js is a lightweight library that can be easily integrated into any project. It aims to be easily configurable while allowing complex user interactions, such as toggling between different measurement outcomes. ## Getting Started + ### Installation + Include `quantum-viz.js` in your HTML page by using it directly from CDN: + ```html ``` + or import it in into your TypeScript package: + ```bash npm i @microsoft/quantum-viz.js ``` ### Usage + 1. Create a `Circuit` JavaScript object (the `Circuit` schema is documented [here](https://github.com/microsoft/quantum-viz.js/wiki/API-schema-reference)): + ```js const sampleCircuit = { - qubits: [ - // ... - ], - operations: [ - // ... - ], + qubits: [ + // ... + ], + operations: [ + // ... + ], }; ``` - 2. Draw it in a `div`: + ```js -const sampleDiv = document.getElementById('sample'); -qviz.draw(sampleCircuit, sampleDiv, qviz.STYLES['Default']); +const sampleDiv = document.getElementById("sample"); +qviz.draw(sampleCircuit, sampleDiv, qviz.STYLES["Default"]); ``` Refer to the [`example`](./example) folder for an example on how to use quantum-viz.js. Notice that in order to open the contents of this folder in a browser you will need first to install from source (see [below](#running-from-source)). @@ -50,7 +58,9 @@ To use this package with Python, use [quantum-viz](/quantum-viz). ## Running from source ### Installing + To build and install this project from source, run the following commands from the root folder of this repository: + ```bash # Install dependencies > npm install @@ -59,7 +69,9 @@ To build and install this project from source, run the following commands from t ``` ### Running tests + To run tests for this project, run the following commands: + ```bash # Installs dependencies (run this step if you haven't) > npm install @@ -68,14 +80,15 @@ To run tests for this project, run the following commands: ``` ## Contributing + Check out our [contributing guidelines](CONTRIBUTING.md) to find out how you can contribute to quantum-viz.js! +## Feedback -## Feedback ## If you have feedback about this library, please let us know by filing a [new issue](https://github.com/microsoft/quantum-viz.js/issues/new/choose)! - ## Reporting Security Issues + Security issues and bugs should be reported privately, via email, to the Microsoft Security Response Center (MSRC) at [secure@microsoft.com](mailto:secure@microsoft.com). You should receive a response within 24 hours. If for some reason you do not, please follow up via @@ -83,12 +96,12 @@ email to ensure we received your original message. Further information, includin [MSRC PGP](https://technet.microsoft.com/en-us/security/dn606155) key, can be found in the [Security TechCenter](https://technet.microsoft.com/en-us/security/default). - ## Trademarks -This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft's Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies. +This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft's Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies. ## Code of Conduct + This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/circuit_vis/SECURITY.md b/circuit_vis/SECURITY.md index f0c2dc14f4..1488eb5dc9 100644 --- a/circuit_vis/SECURITY.md +++ b/circuit_vis/SECURITY.md @@ -12,19 +12,19 @@ If you believe you have found a security vulnerability in any Microsoft-owned re Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). -If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: - * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) - * Full paths of source file(s) related to the manifestation of the issue - * The location of the affected source code (tag/branch/commit or direct URL) - * Any special configuration required to reproduce the issue - * Step-by-step instructions to reproduce the issue - * Proof-of-concept or exploit code (if possible) - * Impact of the issue, including how an attacker might exploit the issue +- Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) +- Full paths of source file(s) related to the manifestation of the issue +- The location of the affected source code (tag/branch/commit or direct URL) +- Any special configuration required to reproduce the issue +- Step-by-step instructions to reproduce the issue +- Proof-of-concept or exploit code (if possible) +- Impact of the issue, including how an attacker might exploit the issue This information will help us triage your report more quickly. diff --git a/circuit_vis/__tests__/gateFormatter.test.ts b/circuit_vis/__tests__/gateFormatter.test.ts index ab277e3aa4..d0448c39f0 100644 --- a/circuit_vis/__tests__/gateFormatter.test.ts +++ b/circuit_vis/__tests__/gateFormatter.test.ts @@ -1,1010 +1,1061 @@ import { - formatGates, - _formatGate, - _createGate, - _measure, - _unitary, - _swap, - _controlledGate, - _groupedOperations, - _classicalControlled, - _zoomButton, -} from '../src/formatters/gateFormatter'; -import { createSvgElement } from '../src/formatters/formatUtils'; -import { Metadata, GateType } from '../src/metadata'; + formatGates, + _formatGate, + _createGate, + _measure, + _unitary, + _swap, + _controlledGate, + _groupedOperations, + _classicalControlled, + _zoomButton, +} from "../src/formatters/gateFormatter"; +import { createSvgElement } from "../src/formatters/formatUtils"; +import { Metadata, GateType } from "../src/metadata"; import { - startX, - startY, - registerHeight, - minGateWidth, - gatePadding, - classicalRegHeight, - controlBtnOffset, - groupBoxPadding, -} from '../src/constants'; + startX, + startY, + registerHeight, + minGateWidth, + gatePadding, + classicalRegHeight, + controlBtnOffset, + groupBoxPadding, +} from "../src/constants"; -describe('Testing _classicalControlled', () => { - test("one 'zero' child", () => { - const metadata: Metadata = { - type: GateType.ClassicalControlled, - x: startX, - controlsY: [startY + classicalRegHeight], - targetsY: [startY], - width: minGateWidth + controlBtnOffset + groupBoxPadding * 2, - label: '', - children: [ - [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, - label: 'X', - controlsY: [], - targetsY: [[startY]], - width: minGateWidth, - }, - ], - [], - ], - }; - expect(_classicalControlled(metadata)).toMatchSnapshot(); - }); - test("one 'one' child", () => { - const metadata: Metadata = { - type: GateType.ClassicalControlled, - x: startX, - controlsY: [startY + classicalRegHeight], - targetsY: [startY], - width: minGateWidth + controlBtnOffset + groupBoxPadding * 2, - label: '', - children: [ - [], - [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, - label: 'X', - controlsY: [], - targetsY: [[startY]], - width: minGateWidth, - }, - ], - ], - }; - expect(_classicalControlled(metadata)).toMatchSnapshot(); - }); - test("one 'zero'/'one' child", () => { - const metadata: Metadata = { - type: GateType.ClassicalControlled, - x: startX, - controlsY: [startY + classicalRegHeight], - targetsY: [startY, startY + classicalRegHeight * 2], - label: '', - width: minGateWidth + controlBtnOffset + groupBoxPadding * 2, - children: [ - [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, - controlsY: [], - targetsY: [[startY]], - label: 'X', - width: minGateWidth, - }, - ], - [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, - controlsY: [], - targetsY: [[startY + classicalRegHeight * 2]], - label: 'H', - width: minGateWidth, - }, - ], - ], - }; - expect(_classicalControlled(metadata)).toMatchSnapshot(); - }); - test("multiple 'zero'/'one' children", () => { - const metadata: Metadata = { - type: GateType.ClassicalControlled, - x: startX, - controlsY: [startY + classicalRegHeight], - targetsY: [startY, startY + classicalRegHeight * 2], - label: '', - width: minGateWidth * 2 + gatePadding * 2 + controlBtnOffset + groupBoxPadding * 2, - children: [ - [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, - controlsY: [], - targetsY: [[startY]], - label: 'X', - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: - startX + - minGateWidth + - minGateWidth / 2 + - gatePadding * 2 + - controlBtnOffset + - groupBoxPadding, - controlsY: [], - targetsY: [[startY]], - label: 'Z', - width: minGateWidth, - }, - ], - [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, - controlsY: [], - targetsY: [[startY + classicalRegHeight * 2]], - label: 'H', - width: minGateWidth, - }, - ], - ], - }; - expect(_classicalControlled(metadata)).toMatchSnapshot(); - }); - test('nested children', () => { - const metadata: Metadata = { - type: GateType.ClassicalControlled, - x: startX, - controlsY: [startY + registerHeight * 2], - targetsY: [startY, startY + registerHeight], - width: minGateWidth * 2 + gatePadding * 6, - label: 'if', - children: [ - [], - [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2 + gatePadding, - label: 'X', - controlsY: [], - targetsY: [[startY]], - width: minGateWidth, - }, - { - type: GateType.ClassicalControlled, - x: startX + minGateWidth + gatePadding * 3, - controlsY: [startY + registerHeight * 3], - targetsY: [startY, startY + registerHeight], - width: minGateWidth + gatePadding * 2, - label: 'if', - children: [ - [], - [ - { - type: GateType.Cnot, - x: startX + minGateWidth + gatePadding * 4 + minGateWidth / 2, - label: 'X', - controlsY: [startY + registerHeight], - targetsY: [startY], - width: minGateWidth, - }, - ], - ], - }, - ], - ], - }; - expect(_classicalControlled(metadata)).toMatchSnapshot(); - }); - test('No htmlClass', () => { - const metadata: Metadata = { - type: GateType.ClassicalControlled, - x: startX, - controlsY: [startY + registerHeight * 2], - targetsY: [startY, startY + registerHeight], - width: minGateWidth * 2 + gatePadding * 4, - label: 'if', - children: [ - [], - [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2 + gatePadding, - label: 'X', - controlsY: [], - targetsY: [[startY]], - width: minGateWidth, - }, - ], - ], - }; - expect(_classicalControlled(metadata)).toMatchSnapshot(); - }); - test('change padding', () => { - const metadata: Metadata = { - type: GateType.ClassicalControlled, - x: startX, - controlsY: [startY + registerHeight * 2], - targetsY: [startY, startY + registerHeight], - width: minGateWidth * 2 + gatePadding * 4, - label: 'if', - children: [ - [], - [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2 + gatePadding, - label: 'X', - controlsY: [], - targetsY: [[startY]], - width: minGateWidth, - }, - ], - ], - }; - expect(_classicalControlled(metadata, 20)).toMatchSnapshot(); - }); -}); - -describe('Testing _groupedOperations', () => { - test('one child', () => { - const metadata: Metadata = { - type: GateType.Group, - x: startX, +describe("Testing _classicalControlled", () => { + test("one 'zero' child", () => { + const metadata: Metadata = { + type: GateType.ClassicalControlled, + x: startX, + controlsY: [startY + classicalRegHeight], + targetsY: [startY], + width: minGateWidth + controlBtnOffset + groupBoxPadding * 2, + label: "", + children: [ + [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, + label: "X", controlsY: [], - targetsY: [startY], - label: '', - width: minGateWidth + groupBoxPadding * 2, - children: [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2 + groupBoxPadding, - controlsY: [], - targetsY: [[startY]], - label: 'X', - width: minGateWidth, - }, - ], - }; - expect(_groupedOperations(metadata, 0)).toMatchSnapshot(); - }); - test('children on consecutive registers', () => { - const metadata: Metadata = { - type: GateType.Group, - x: startX, + targetsY: [[startY]], + width: minGateWidth, + }, + ], + [], + ], + }; + expect(_classicalControlled(metadata)).toMatchSnapshot(); + }); + test("one 'one' child", () => { + const metadata: Metadata = { + type: GateType.ClassicalControlled, + x: startX, + controlsY: [startY + classicalRegHeight], + targetsY: [startY], + width: minGateWidth + controlBtnOffset + groupBoxPadding * 2, + label: "", + children: [ + [], + [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, + label: "X", controlsY: [], - targetsY: [startY, startY + registerHeight], - label: '', - width: minGateWidth + groupBoxPadding * 2, - children: [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2 + groupBoxPadding, - controlsY: [], - targetsY: [[startY]], - label: 'X', - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + minGateWidth / 2 + groupBoxPadding, - controlsY: [], - targetsY: [[startY + registerHeight]], - label: 'H', - width: minGateWidth, - }, - ], - }; - expect(_groupedOperations(metadata, 0)).toMatchSnapshot(); - }); - test('children on non-consecutive registers', () => { - const metadata: Metadata = { - type: GateType.Group, - x: startX, + targetsY: [[startY]], + width: minGateWidth, + }, + ], + ], + }; + expect(_classicalControlled(metadata)).toMatchSnapshot(); + }); + test("one 'zero'/'one' child", () => { + const metadata: Metadata = { + type: GateType.ClassicalControlled, + x: startX, + controlsY: [startY + classicalRegHeight], + targetsY: [startY, startY + classicalRegHeight * 2], + label: "", + width: minGateWidth + controlBtnOffset + groupBoxPadding * 2, + children: [ + [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, controlsY: [], - targetsY: [startY, startY + registerHeight * 2], - label: '', - width: minGateWidth + groupBoxPadding * 2, - children: [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2 + groupBoxPadding, - controlsY: [], - targetsY: [[startY]], - label: 'X', - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + minGateWidth / 2 + groupBoxPadding, - controlsY: [], - targetsY: [[startY + registerHeight * 2]], - label: 'H', - width: minGateWidth, - }, - ], - }; - expect(_groupedOperations(metadata, 0)).toMatchSnapshot(); - }); - test('children on same register', () => { - const metadata: Metadata = { - type: GateType.Group, - x: startX, + targetsY: [[startY]], + label: "X", + width: minGateWidth, + }, + ], + [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, controlsY: [], - targetsY: [startY], - label: '', - width: minGateWidth * 2 + gatePadding * 2 + groupBoxPadding * 2, - children: [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2 + groupBoxPadding, - controlsY: [], - targetsY: [[startY]], - label: 'X', - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + minGateWidth + minGateWidth / 2 + gatePadding * 2 + groupBoxPadding, - controlsY: [], - targetsY: [[startY]], - label: 'Z', - width: minGateWidth, - }, - ], - }; - expect(_groupedOperations(metadata, 0)).toMatchSnapshot(); - }); - test('multiple children', () => { - const metadata: Metadata = { - type: GateType.Group, - x: startX, + targetsY: [[startY + classicalRegHeight * 2]], + label: "H", + width: minGateWidth, + }, + ], + ], + }; + expect(_classicalControlled(metadata)).toMatchSnapshot(); + }); + test("multiple 'zero'/'one' children", () => { + const metadata: Metadata = { + type: GateType.ClassicalControlled, + x: startX, + controlsY: [startY + classicalRegHeight], + targetsY: [startY, startY + classicalRegHeight * 2], + label: "", + width: + minGateWidth * 2 + + gatePadding * 2 + + controlBtnOffset + + groupBoxPadding * 2, + children: [ + [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, controlsY: [], - targetsY: [startY, startY + registerHeight], - label: '', - width: minGateWidth * 2 + gatePadding * 2 + groupBoxPadding * 2, - children: [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2 + groupBoxPadding, - controlsY: [], - targetsY: [[startY]], - label: 'X', - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + minGateWidth + minGateWidth / 2 + gatePadding * 2 + groupBoxPadding, - controlsY: [], - targetsY: [[startY]], - label: 'Z', - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + minGateWidth / 2 + groupBoxPadding, - controlsY: [], - targetsY: [[startY + registerHeight]], - label: 'H', - width: minGateWidth, - }, - ], - }; - expect(_groupedOperations(metadata, 0)).toMatchSnapshot(); - }); - test('nested children', () => { - const metadata: Metadata = { - type: GateType.Group, - x: startX, + targetsY: [[startY]], + label: "X", + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: + startX + + minGateWidth + + minGateWidth / 2 + + gatePadding * 2 + + controlBtnOffset + + groupBoxPadding, + controlsY: [], + targetsY: [[startY]], + label: "Z", + width: minGateWidth, + }, + ], + [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, controlsY: [], + targetsY: [[startY + classicalRegHeight * 2]], + label: "H", + width: minGateWidth, + }, + ], + ], + }; + expect(_classicalControlled(metadata)).toMatchSnapshot(); + }); + test("nested children", () => { + const metadata: Metadata = { + type: GateType.ClassicalControlled, + x: startX, + controlsY: [startY + registerHeight * 2], + targetsY: [startY, startY + registerHeight], + width: minGateWidth * 2 + gatePadding * 6, + label: "if", + children: [ + [], + [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + gatePadding, + label: "X", + controlsY: [], + targetsY: [[startY]], + width: minGateWidth, + }, + { + type: GateType.ClassicalControlled, + x: startX + minGateWidth + gatePadding * 3, + controlsY: [startY + registerHeight * 3], targetsY: [startY, startY + registerHeight], - label: '', - width: minGateWidth * 2 + gatePadding * 2 + groupBoxPadding * 4, + width: minGateWidth + gatePadding * 2, + label: "if", children: [ + [], + [ { - type: GateType.Group, - x: startX + gatePadding, - controlsY: [], - targetsY: [startY], - label: '', - width: minGateWidth * 2 + gatePadding * 2 + groupBoxPadding * 2, - children: [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2 + groupBoxPadding * 2, - controlsY: [], - targetsY: [[startY]], - label: 'X', - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + minGateWidth + minGateWidth / 2 + gatePadding * 2 + groupBoxPadding * 2, - controlsY: [], - targetsY: [[startY]], - label: 'Z', - width: minGateWidth, - }, - ], - }, - { - type: GateType.Unitary, - x: startX + minGateWidth + gatePadding + groupBoxPadding * 2, - controlsY: [], - targetsY: [[startY + registerHeight]], - label: 'H', - width: minGateWidth, + type: GateType.Cnot, + x: startX + minGateWidth + gatePadding * 4 + minGateWidth / 2, + label: "X", + controlsY: [startY + registerHeight], + targetsY: [startY], + width: minGateWidth, }, + ], ], - }; - expect(_groupedOperations(metadata, 0)).toMatchSnapshot(); - }); + }, + ], + ], + }; + expect(_classicalControlled(metadata)).toMatchSnapshot(); + }); + test("No htmlClass", () => { + const metadata: Metadata = { + type: GateType.ClassicalControlled, + x: startX, + controlsY: [startY + registerHeight * 2], + targetsY: [startY, startY + registerHeight], + width: minGateWidth * 2 + gatePadding * 4, + label: "if", + children: [ + [], + [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + gatePadding, + label: "X", + controlsY: [], + targetsY: [[startY]], + width: minGateWidth, + }, + ], + ], + }; + expect(_classicalControlled(metadata)).toMatchSnapshot(); + }); + test("change padding", () => { + const metadata: Metadata = { + type: GateType.ClassicalControlled, + x: startX, + controlsY: [startY + registerHeight * 2], + targetsY: [startY, startY + registerHeight], + width: minGateWidth * 2 + gatePadding * 4, + label: "if", + children: [ + [], + [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + gatePadding, + label: "X", + controlsY: [], + targetsY: [[startY]], + width: minGateWidth, + }, + ], + ], + }; + expect(_classicalControlled(metadata, 20)).toMatchSnapshot(); + }); }); -describe('Testing _controlledGate', () => { - test('CNOT gate', () => { - const metadata: Metadata = { - type: GateType.Cnot, - label: 'X', - x: startX, - controlsY: [startY], - targetsY: [startY + registerHeight], - width: minGateWidth, - }; - let svg: SVGElement = _controlledGate(metadata, 0); - expect(svg).toMatchSnapshot(); +describe("Testing _groupedOperations", () => { + test("one child", () => { + const metadata: Metadata = { + type: GateType.Group, + x: startX, + controlsY: [], + targetsY: [startY], + label: "", + width: minGateWidth + groupBoxPadding * 2, + children: [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + groupBoxPadding, + controlsY: [], + targetsY: [[startY]], + label: "X", + width: minGateWidth, + }, + ], + }; + expect(_groupedOperations(metadata, 0)).toMatchSnapshot(); + }); + test("children on consecutive registers", () => { + const metadata: Metadata = { + type: GateType.Group, + x: startX, + controlsY: [], + targetsY: [startY, startY + registerHeight], + label: "", + width: minGateWidth + groupBoxPadding * 2, + children: [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + groupBoxPadding, + controlsY: [], + targetsY: [[startY]], + label: "X", + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + groupBoxPadding, + controlsY: [], + targetsY: [[startY + registerHeight]], + label: "H", + width: minGateWidth, + }, + ], + }; + expect(_groupedOperations(metadata, 0)).toMatchSnapshot(); + }); + test("children on non-consecutive registers", () => { + const metadata: Metadata = { + type: GateType.Group, + x: startX, + controlsY: [], + targetsY: [startY, startY + registerHeight * 2], + label: "", + width: minGateWidth + groupBoxPadding * 2, + children: [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + groupBoxPadding, + controlsY: [], + targetsY: [[startY]], + label: "X", + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + groupBoxPadding, + controlsY: [], + targetsY: [[startY + registerHeight * 2]], + label: "H", + width: minGateWidth, + }, + ], + }; + expect(_groupedOperations(metadata, 0)).toMatchSnapshot(); + }); + test("children on same register", () => { + const metadata: Metadata = { + type: GateType.Group, + x: startX, + controlsY: [], + targetsY: [startY], + label: "", + width: minGateWidth * 2 + gatePadding * 2 + groupBoxPadding * 2, + children: [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + groupBoxPadding, + controlsY: [], + targetsY: [[startY]], + label: "X", + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: + startX + + minGateWidth + + minGateWidth / 2 + + gatePadding * 2 + + groupBoxPadding, + controlsY: [], + targetsY: [[startY]], + label: "Z", + width: minGateWidth, + }, + ], + }; + expect(_groupedOperations(metadata, 0)).toMatchSnapshot(); + }); + test("multiple children", () => { + const metadata: Metadata = { + type: GateType.Group, + x: startX, + controlsY: [], + targetsY: [startY, startY + registerHeight], + label: "", + width: minGateWidth * 2 + gatePadding * 2 + groupBoxPadding * 2, + children: [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + groupBoxPadding, + controlsY: [], + targetsY: [[startY]], + label: "X", + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: + startX + + minGateWidth + + minGateWidth / 2 + + gatePadding * 2 + + groupBoxPadding, + controlsY: [], + targetsY: [[startY]], + label: "Z", + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + groupBoxPadding, + controlsY: [], + targetsY: [[startY + registerHeight]], + label: "H", + width: minGateWidth, + }, + ], + }; + expect(_groupedOperations(metadata, 0)).toMatchSnapshot(); + }); + test("nested children", () => { + const metadata: Metadata = { + type: GateType.Group, + x: startX, + controlsY: [], + targetsY: [startY, startY + registerHeight], + label: "", + width: minGateWidth * 2 + gatePadding * 2 + groupBoxPadding * 4, + children: [ + { + type: GateType.Group, + x: startX + gatePadding, + controlsY: [], + targetsY: [startY], + label: "", + width: minGateWidth * 2 + gatePadding * 2 + groupBoxPadding * 2, + children: [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + groupBoxPadding * 2, + controlsY: [], + targetsY: [[startY]], + label: "X", + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: + startX + + minGateWidth + + minGateWidth / 2 + + gatePadding * 2 + + groupBoxPadding * 2, + controlsY: [], + targetsY: [[startY]], + label: "Z", + width: minGateWidth, + }, + ], + }, + { + type: GateType.Unitary, + x: startX + minGateWidth + gatePadding + groupBoxPadding * 2, + controlsY: [], + targetsY: [[startY + registerHeight]], + label: "H", + width: minGateWidth, + }, + ], + }; + expect(_groupedOperations(metadata, 0)).toMatchSnapshot(); + }); +}); - // Flip target and control - metadata.controlsY = [startY + registerHeight]; - metadata.targetsY = [startY]; - svg = _controlledGate(metadata, 0); - expect(svg).toMatchSnapshot(); - }); - test('SWAP gate', () => { - const metadata: Metadata = { - type: GateType.Swap, - label: '', - x: startX, - controlsY: [startY], - targetsY: [startY + registerHeight, startY + registerHeight * 2], - width: minGateWidth, - }; - // Control on top - let svg: SVGElement = _controlledGate(metadata, 0); - expect(svg).toMatchSnapshot(); +describe("Testing _controlledGate", () => { + test("CNOT gate", () => { + const metadata: Metadata = { + type: GateType.Cnot, + label: "X", + x: startX, + controlsY: [startY], + targetsY: [startY + registerHeight], + width: minGateWidth, + }; + let svg: SVGElement = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); - // Control on bottom - metadata.controlsY = [startY + registerHeight * 2]; - metadata.targetsY = [startY, startY + registerHeight]; - svg = _controlledGate(metadata, 0); - expect(svg).toMatchSnapshot(); + // Flip target and control + metadata.controlsY = [startY + registerHeight]; + metadata.targetsY = [startY]; + svg = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); + }); + test("SWAP gate", () => { + const metadata: Metadata = { + type: GateType.Swap, + label: "", + x: startX, + controlsY: [startY], + targetsY: [startY + registerHeight, startY + registerHeight * 2], + width: minGateWidth, + }; + // Control on top + let svg: SVGElement = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); - // Control in middle - metadata.controlsY = [startY + registerHeight]; - metadata.targetsY = [startY, startY + registerHeight * 2]; - svg = _controlledGate(metadata, 0); - expect(svg).toMatchSnapshot(); - }); - test('Controlled U gate with 1 control + 1 target', () => { - const metadata: Metadata = { - type: GateType.ControlledUnitary, - label: 'Foo', - x: startX, - controlsY: [startY], - targetsY: [[startY + registerHeight]], - width: 45, - }; - let svg: SVGElement = _controlledGate(metadata, 0); - expect(svg).toMatchSnapshot(); + // Control on bottom + metadata.controlsY = [startY + registerHeight * 2]; + metadata.targetsY = [startY, startY + registerHeight]; + svg = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); - // Flip target and control - metadata.controlsY = [startY + registerHeight]; - metadata.targetsY = [[startY]]; - svg = _controlledGate(metadata, 0); - expect(svg).toMatchSnapshot(); - }); - test('Controlled U gate with multiple controls + 1 target', () => { - const metadata: Metadata = { - type: GateType.ControlledUnitary, - label: 'Foo', - x: startX, - controlsY: [startY, startY + registerHeight], - targetsY: [[startY + registerHeight * 2]], - width: 45, - }; - // Target on bottom - let svg: SVGElement = _controlledGate(metadata, 0); - expect(svg).toMatchSnapshot(); + // Control in middle + metadata.controlsY = [startY + registerHeight]; + metadata.targetsY = [startY, startY + registerHeight * 2]; + svg = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); + }); + test("Controlled U gate with 1 control + 1 target", () => { + const metadata: Metadata = { + type: GateType.ControlledUnitary, + label: "Foo", + x: startX, + controlsY: [startY], + targetsY: [[startY + registerHeight]], + width: 45, + }; + let svg: SVGElement = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); - // Target on top - metadata.controlsY = [startY + registerHeight, startY + registerHeight * 2]; - metadata.targetsY = [[startY]]; - svg = _controlledGate(metadata, 0); - expect(svg).toMatchSnapshot(); + // Flip target and control + metadata.controlsY = [startY + registerHeight]; + metadata.targetsY = [[startY]]; + svg = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); + }); + test("Controlled U gate with multiple controls + 1 target", () => { + const metadata: Metadata = { + type: GateType.ControlledUnitary, + label: "Foo", + x: startX, + controlsY: [startY, startY + registerHeight], + targetsY: [[startY + registerHeight * 2]], + width: 45, + }; + // Target on bottom + let svg: SVGElement = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); - // Target in middle - metadata.controlsY = [startY, startY + registerHeight * 2]; - metadata.targetsY = [[startY + registerHeight]]; - svg = _controlledGate(metadata, 0); - expect(svg).toMatchSnapshot(); - }); - test('Controlled U gate with 1 control + 2 targets', () => { - const metadata: Metadata = { - type: GateType.ControlledUnitary, - label: 'Foo', - x: startX, - controlsY: [startY + registerHeight * 2], - targetsY: [[startY, startY + registerHeight]], - width: 45, - }; - // Control on bottom - let svg: SVGElement = _controlledGate(metadata, 0); - expect(svg).toMatchSnapshot(); + // Target on top + metadata.controlsY = [startY + registerHeight, startY + registerHeight * 2]; + metadata.targetsY = [[startY]]; + svg = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); - // Control on top - metadata.controlsY = [startY]; - metadata.targetsY = [[startY + registerHeight, startY + registerHeight * 2]]; - svg = _controlledGate(metadata, 0); - expect(svg).toMatchSnapshot(); + // Target in middle + metadata.controlsY = [startY, startY + registerHeight * 2]; + metadata.targetsY = [[startY + registerHeight]]; + svg = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); + }); + test("Controlled U gate with 1 control + 2 targets", () => { + const metadata: Metadata = { + type: GateType.ControlledUnitary, + label: "Foo", + x: startX, + controlsY: [startY + registerHeight * 2], + targetsY: [[startY, startY + registerHeight]], + width: 45, + }; + // Control on bottom + let svg: SVGElement = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); - // Control in middle - metadata.controlsY = [startY + registerHeight]; - metadata.targetsY = [[startY], [startY + registerHeight * 2]]; - svg = _controlledGate(metadata, 0); - expect(svg).toMatchSnapshot(); - }); - test('Controlled U gate with 2 controls + 2 targets', () => { - const metadata: Metadata = { - type: GateType.ControlledUnitary, - label: 'Foo', - x: startX, - controlsY: [startY + registerHeight * 2, startY + registerHeight * 3], - targetsY: [[startY, startY + registerHeight]], - width: 45, - }; - // Controls on bottom - let svg: SVGElement = _controlledGate(metadata, 0); - expect(svg).toMatchSnapshot(); + // Control on top + metadata.controlsY = [startY]; + metadata.targetsY = [ + [startY + registerHeight, startY + registerHeight * 2], + ]; + svg = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); - // Controls on top - metadata.controlsY = [startY, startY + registerHeight]; - metadata.targetsY = [[startY + registerHeight * 2, startY + registerHeight * 3]]; - svg = _controlledGate(metadata, 0); - expect(svg).toMatchSnapshot(); + // Control in middle + metadata.controlsY = [startY + registerHeight]; + metadata.targetsY = [[startY], [startY + registerHeight * 2]]; + svg = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); + }); + test("Controlled U gate with 2 controls + 2 targets", () => { + const metadata: Metadata = { + type: GateType.ControlledUnitary, + label: "Foo", + x: startX, + controlsY: [startY + registerHeight * 2, startY + registerHeight * 3], + targetsY: [[startY, startY + registerHeight]], + width: 45, + }; + // Controls on bottom + let svg: SVGElement = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); - // Controls in middle - metadata.controlsY = [startY + registerHeight, startY + registerHeight * 2]; - metadata.targetsY = [[startY], [startY + registerHeight * 3]]; - svg = _controlledGate(metadata, 0); - expect(svg).toMatchSnapshot(); + // Controls on top + metadata.controlsY = [startY, startY + registerHeight]; + metadata.targetsY = [ + [startY + registerHeight * 2, startY + registerHeight * 3], + ]; + svg = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); - // Interleaved controls/targets - metadata.controlsY = [startY + registerHeight, startY + registerHeight * 3]; - metadata.targetsY = [[startY], [startY + registerHeight * 2]]; - svg = _controlledGate(metadata, 0); - expect(svg).toMatchSnapshot(); - }); - test('Invalid gate', () => { - const metadata: Metadata = { - type: GateType.Measure, - label: 'X', - x: startX, - controlsY: [startY], - targetsY: [startY + registerHeight], - width: minGateWidth, - }; - expect(() => _controlledGate(metadata, 0)).toThrowError( - `ERROR: Unrecognized gate: X of type ${GateType.Measure}`, - ); - }); -}); + // Controls in middle + metadata.controlsY = [startY + registerHeight, startY + registerHeight * 2]; + metadata.targetsY = [[startY], [startY + registerHeight * 3]]; + svg = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); -describe('Testing _swap', () => { + // Interleaved controls/targets + metadata.controlsY = [startY + registerHeight, startY + registerHeight * 3]; + metadata.targetsY = [[startY], [startY + registerHeight * 2]]; + svg = _controlledGate(metadata, 0); + expect(svg).toMatchSnapshot(); + }); + test("Invalid gate", () => { const metadata: Metadata = { - type: GateType.Measure, - label: 'SWAP', - x: startX, - controlsY: [], - targetsY: [startY + registerHeight], - width: minGateWidth, + type: GateType.Measure, + label: "X", + x: startX, + controlsY: [startY], + targetsY: [startY + registerHeight], + width: minGateWidth, }; + expect(() => _controlledGate(metadata, 0)).toThrowError( + `ERROR: Unrecognized gate: X of type ${GateType.Measure}`, + ); + }); +}); + +describe("Testing _swap", () => { + const metadata: Metadata = { + type: GateType.Measure, + label: "SWAP", + x: startX, + controlsY: [], + targetsY: [startY + registerHeight], + width: minGateWidth, + }; - test('Adjacent swap', () => { - metadata.targetsY = [startY, startY + registerHeight]; - let svg: SVGElement = _swap(metadata, 0); - expect(svg).toMatchSnapshot(); - // Flip target and control - metadata.targetsY = [startY + registerHeight, startY]; - svg = _swap(metadata, 0); - expect(svg).toMatchSnapshot(); - }); - test('Non-adjacent swap', () => { - metadata.targetsY = [startY, startY + registerHeight * 2]; - let svg: SVGElement = _swap(metadata, 0); - expect(svg).toMatchSnapshot(); - // Flip target and control - metadata.targetsY = [startY + registerHeight * 2, startY]; - svg = _swap(metadata, 0); - expect(svg).toMatchSnapshot(); - }); + test("Adjacent swap", () => { + metadata.targetsY = [startY, startY + registerHeight]; + let svg: SVGElement = _swap(metadata, 0); + expect(svg).toMatchSnapshot(); + // Flip target and control + metadata.targetsY = [startY + registerHeight, startY]; + svg = _swap(metadata, 0); + expect(svg).toMatchSnapshot(); + }); + test("Non-adjacent swap", () => { + metadata.targetsY = [startY, startY + registerHeight * 2]; + let svg: SVGElement = _swap(metadata, 0); + expect(svg).toMatchSnapshot(); + // Flip target and control + metadata.targetsY = [startY + registerHeight * 2, startY]; + svg = _swap(metadata, 0); + expect(svg).toMatchSnapshot(); + }); }); -describe('Testing _unitary', () => { - test('Single qubit unitary', () => { - expect(_unitary('H', startX, [[startY]], minGateWidth)).toMatchSnapshot(); - }); - test('Multiqubit unitary on consecutive registers', () => { - let svg: SVGElement = _unitary('ZZ', startX, [[startY, startY + registerHeight]], minGateWidth); - expect(svg).toMatchSnapshot(); - svg = _unitary('ZZZ', startX, [[startY, startY + registerHeight, startY + registerHeight * 2]], minGateWidth); - expect(svg).toMatchSnapshot(); - }); - test('Multiqubit unitary on non-consecutive registers', () => { - // Dashed line between unitaries - let svg: SVGElement = _unitary('ZZ', startX, [[startY], [startY + registerHeight * 2]], minGateWidth); - expect(svg).toMatchSnapshot(); - svg = _unitary( - 'ZZZ', - startX, - [[startY], [startY + registerHeight * 2, startY + registerHeight * 3]], - minGateWidth, - ); - expect(svg).toMatchSnapshot(); - // Solid line - svg = _unitary('ZZ', startX, [[startY], [startY + registerHeight * 2]], minGateWidth, undefined, false); - expect(svg).toMatchSnapshot(); - svg = _unitary( - 'ZZZ', - startX, - [[startY], [startY + registerHeight * 2, startY + registerHeight * 3]], - minGateWidth, - undefined, - false, - ); - expect(svg).toMatchSnapshot(); - }); - test('No y coords', () => { - expect(() => _unitary('ZZ', startX, [], minGateWidth)).toThrowError( - 'Failed to render unitary gate (ZZ): has no y-values', - ); - }); +describe("Testing _unitary", () => { + test("Single qubit unitary", () => { + expect(_unitary("H", startX, [[startY]], minGateWidth)).toMatchSnapshot(); + }); + test("Multiqubit unitary on consecutive registers", () => { + let svg: SVGElement = _unitary( + "ZZ", + startX, + [[startY, startY + registerHeight]], + minGateWidth, + ); + expect(svg).toMatchSnapshot(); + svg = _unitary( + "ZZZ", + startX, + [[startY, startY + registerHeight, startY + registerHeight * 2]], + minGateWidth, + ); + expect(svg).toMatchSnapshot(); + }); + test("Multiqubit unitary on non-consecutive registers", () => { + // Dashed line between unitaries + let svg: SVGElement = _unitary( + "ZZ", + startX, + [[startY], [startY + registerHeight * 2]], + minGateWidth, + ); + expect(svg).toMatchSnapshot(); + svg = _unitary( + "ZZZ", + startX, + [[startY], [startY + registerHeight * 2, startY + registerHeight * 3]], + minGateWidth, + ); + expect(svg).toMatchSnapshot(); + // Solid line + svg = _unitary( + "ZZ", + startX, + [[startY], [startY + registerHeight * 2]], + minGateWidth, + undefined, + false, + ); + expect(svg).toMatchSnapshot(); + svg = _unitary( + "ZZZ", + startX, + [[startY], [startY + registerHeight * 2, startY + registerHeight * 3]], + minGateWidth, + undefined, + false, + ); + expect(svg).toMatchSnapshot(); + }); + test("No y coords", () => { + expect(() => _unitary("ZZ", startX, [], minGateWidth)).toThrowError( + "Failed to render unitary gate (ZZ): has no y-values", + ); + }); }); -describe('Testing _measure', () => { - test('1 qubit + 1 classical registers', () => { - expect(_measure(startX, startY)).toMatchSnapshot(); - }); - test('2 qubit + 1 classical registers', () => { - expect(_measure(startX, startY)).toMatchSnapshot(); - }); - test('2 qubit + 2 classical registers', () => { - expect(_measure(startX, startY)).toMatchSnapshot(); - expect(_measure(startX, startY + registerHeight)).toMatchSnapshot(); - }); +describe("Testing _measure", () => { + test("1 qubit + 1 classical registers", () => { + expect(_measure(startX, startY)).toMatchSnapshot(); + }); + test("2 qubit + 1 classical registers", () => { + expect(_measure(startX, startY)).toMatchSnapshot(); + }); + test("2 qubit + 2 classical registers", () => { + expect(_measure(startX, startY)).toMatchSnapshot(); + expect(_measure(startX, startY + registerHeight)).toMatchSnapshot(); + }); }); -describe('Testing _createGate', () => { - const metadata: Metadata = { - type: GateType.Invalid, - x: 0, - controlsY: [], - targetsY: [], - label: '', - width: -1, - dataAttributes: { a: '1', b: '2' }, - }; - const line: SVGElement = createSvgElement('line'); - test('Empty gate', () => { - expect(_createGate([line], metadata, 0).outerHTML).toEqual( - '', - ); - }); - test('Expanded gate', () => { - if (metadata.dataAttributes) metadata.dataAttributes['expanded'] = 'true'; - expect(_createGate([line], metadata, 0)).toMatchSnapshot(); - }); +describe("Testing _createGate", () => { + const metadata: Metadata = { + type: GateType.Invalid, + x: 0, + controlsY: [], + targetsY: [], + label: "", + width: -1, + dataAttributes: { a: "1", b: "2" }, + }; + const line: SVGElement = createSvgElement("line"); + test("Empty gate", () => { + expect(_createGate([line], metadata, 0).outerHTML).toEqual( + '', + ); + }); + test("Expanded gate", () => { + if (metadata.dataAttributes) metadata.dataAttributes["expanded"] = "true"; + expect(_createGate([line], metadata, 0)).toMatchSnapshot(); + }); }); -describe('Testing _zoomButton', () => { - const metadata: Metadata = { - type: GateType.Group, - x: startX, +describe("Testing _zoomButton", () => { + const metadata: Metadata = { + type: GateType.Group, + x: startX, + controlsY: [], + targetsY: [startY], + label: "", + width: minGateWidth + groupBoxPadding * 2, + children: [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + groupBoxPadding, controlsY: [], - targetsY: [startY], - label: '', - width: minGateWidth + groupBoxPadding * 2, - children: [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2 + groupBoxPadding, - controlsY: [], - targetsY: [[startY]], - label: 'X', - width: minGateWidth, - }, - ], - }; + targetsY: [[startY]], + label: "X", + width: minGateWidth, + }, + ], + }; - test('Expanded gate', () => { - if (metadata.dataAttributes) { - metadata.dataAttributes['expanded'] = 'true'; - metadata.dataAttributes['zoom-in'] = 'true'; - } - expect(_zoomButton(metadata, 0)).toMatchSnapshot(); - }); - test('Non-expanded with no children gate', () => { - if (metadata.dataAttributes) { - delete metadata.dataAttributes['expanded']; - delete metadata.dataAttributes['zoom-in']; - } - expect(_zoomButton(metadata, 0)).toMatchSnapshot(); - }); - test('Non-expanded with children gate', () => { - if (metadata.dataAttributes) { - delete metadata.dataAttributes['expanded']; - metadata.dataAttributes['zoom-in'] = 'true'; - } - expect(_zoomButton(metadata, 0)).toMatchSnapshot(); - }); - test('Expanded with children gate', () => { - if (metadata.dataAttributes) { - metadata.dataAttributes['expanded'] = 'true'; - metadata.dataAttributes['zoom-in'] = 'true'; - } - expect(_zoomButton(metadata, 0)).toMatchSnapshot(); - }); + test("Expanded gate", () => { + if (metadata.dataAttributes) { + metadata.dataAttributes["expanded"] = "true"; + metadata.dataAttributes["zoom-in"] = "true"; + } + expect(_zoomButton(metadata, 0)).toMatchSnapshot(); + }); + test("Non-expanded with no children gate", () => { + if (metadata.dataAttributes) { + delete metadata.dataAttributes["expanded"]; + delete metadata.dataAttributes["zoom-in"]; + } + expect(_zoomButton(metadata, 0)).toMatchSnapshot(); + }); + test("Non-expanded with children gate", () => { + if (metadata.dataAttributes) { + delete metadata.dataAttributes["expanded"]; + metadata.dataAttributes["zoom-in"] = "true"; + } + expect(_zoomButton(metadata, 0)).toMatchSnapshot(); + }); + test("Expanded with children gate", () => { + if (metadata.dataAttributes) { + metadata.dataAttributes["expanded"] = "true"; + metadata.dataAttributes["zoom-in"] = "true"; + } + expect(_zoomButton(metadata, 0)).toMatchSnapshot(); + }); }); -describe('Testing _formatGate', () => { - test('measure gate', () => { - const metadata: Metadata = { - type: GateType.Measure, - x: startX, - controlsY: [startY], - targetsY: [startY + registerHeight], - label: '', - width: minGateWidth, - }; - expect(_formatGate(metadata)).toMatchSnapshot(); - }); - test('single-qubit unitary gate', () => { - const metadata: Metadata = { - type: GateType.Unitary, - x: startX, - controlsY: [], - targetsY: [[startY]], - label: 'H', - width: minGateWidth, - }; - expect(_formatGate(metadata)).toMatchSnapshot(); - }); - test('single-qubit unitary gate with arguments', () => { - const metadata: Metadata = { - type: GateType.Unitary, - x: startX, - controlsY: [], - targetsY: [[startY]], - label: 'Ry', - displayArgs: '(0.25)', - width: 52, - }; - expect(_formatGate(metadata)).toMatchSnapshot(); - }); - test('multi-qubit unitary gate', () => { - const metadata: Metadata = { - type: GateType.Unitary, - x: startX, - controlsY: [], - targetsY: [[startY, startY + registerHeight]], - label: 'U', - width: minGateWidth, - }; - expect(_formatGate(metadata)).toMatchSnapshot(); - }); - test('multi-qubit unitary gate with arguments', () => { - const metadata: Metadata = { - type: GateType.ControlledUnitary, - x: startX, - controlsY: [], - targetsY: [[startY, startY + registerHeight]], - label: 'U', - displayArgs: "('foo', 'bar')", - width: 77, - }; - expect(_formatGate(metadata)).toMatchSnapshot(); - }); - test('swap gate', () => { - const metadata: Metadata = { - type: GateType.Swap, - x: startX, - controlsY: [], - targetsY: [startY, startY + registerHeight], - label: '', - width: minGateWidth, - }; - expect(_formatGate(metadata)).toMatchSnapshot(); - }); - test('controlled swap gate', () => { - const metadata: Metadata = { - type: GateType.Swap, - x: startX, - controlsY: [startY], - targetsY: [startY + registerHeight, startY + registerHeight * 2], - label: '', - width: minGateWidth, - }; - expect(_formatGate(metadata)).toMatchSnapshot(); - }); - test('CNOT gate', () => { - const metadata: Metadata = { - type: GateType.Cnot, - x: startX, - controlsY: [startY], - targetsY: [startY + registerHeight], - label: 'X', - width: minGateWidth, - }; - expect(_formatGate(metadata)).toMatchSnapshot(); - }); - test('controlled unitary gate', () => { - const metadata: Metadata = { - type: GateType.ControlledUnitary, - x: startX, - controlsY: [startY], - targetsY: [[startY + registerHeight]], - label: 'U', - width: minGateWidth, - }; - expect(_formatGate(metadata)).toMatchSnapshot(); - }); - test('controlled unitary gate with arguments', () => { - const metadata: Metadata = { - type: GateType.ControlledUnitary, - x: startX, - controlsY: [startY], - targetsY: [[startY + registerHeight]], - label: 'U', - displayArgs: "('foo', 'bar')", - width: 77, - }; - expect(_formatGate(metadata)).toMatchSnapshot(); - }); - test('classically controlled gate', () => { - const metadata: Metadata = { - type: GateType.ClassicalControlled, - x: startX, - controlsY: [startY + registerHeight * 2], - targetsY: [startY, startY + registerHeight], - label: '', - width: minGateWidth, - }; - expect(_formatGate(metadata)).toMatchSnapshot(); - }); - test('gate with metadata', () => { - const metadata: Metadata = { - type: GateType.Unitary, - x: startX, - controlsY: [], - targetsY: [[startY]], - label: 'H', - width: minGateWidth, - dataAttributes: { a: '1', b: '2' }, - }; - expect(_formatGate(metadata)).toMatchSnapshot(); - }); - test('invalid gate', () => { - const metadata: Metadata = { - type: GateType.Invalid, - x: startX, - controlsY: [startY], - targetsY: [startY + registerHeight], - label: 'Foo', - width: 48, - }; - expect(() => _formatGate(metadata)).toThrowError(`ERROR: unknown gate (Foo) of type ${GateType.Invalid}.`); - }); +describe("Testing _formatGate", () => { + test("measure gate", () => { + const metadata: Metadata = { + type: GateType.Measure, + x: startX, + controlsY: [startY], + targetsY: [startY + registerHeight], + label: "", + width: minGateWidth, + }; + expect(_formatGate(metadata)).toMatchSnapshot(); + }); + test("single-qubit unitary gate", () => { + const metadata: Metadata = { + type: GateType.Unitary, + x: startX, + controlsY: [], + targetsY: [[startY]], + label: "H", + width: minGateWidth, + }; + expect(_formatGate(metadata)).toMatchSnapshot(); + }); + test("single-qubit unitary gate with arguments", () => { + const metadata: Metadata = { + type: GateType.Unitary, + x: startX, + controlsY: [], + targetsY: [[startY]], + label: "Ry", + displayArgs: "(0.25)", + width: 52, + }; + expect(_formatGate(metadata)).toMatchSnapshot(); + }); + test("multi-qubit unitary gate", () => { + const metadata: Metadata = { + type: GateType.Unitary, + x: startX, + controlsY: [], + targetsY: [[startY, startY + registerHeight]], + label: "U", + width: minGateWidth, + }; + expect(_formatGate(metadata)).toMatchSnapshot(); + }); + test("multi-qubit unitary gate with arguments", () => { + const metadata: Metadata = { + type: GateType.ControlledUnitary, + x: startX, + controlsY: [], + targetsY: [[startY, startY + registerHeight]], + label: "U", + displayArgs: "('foo', 'bar')", + width: 77, + }; + expect(_formatGate(metadata)).toMatchSnapshot(); + }); + test("swap gate", () => { + const metadata: Metadata = { + type: GateType.Swap, + x: startX, + controlsY: [], + targetsY: [startY, startY + registerHeight], + label: "", + width: minGateWidth, + }; + expect(_formatGate(metadata)).toMatchSnapshot(); + }); + test("controlled swap gate", () => { + const metadata: Metadata = { + type: GateType.Swap, + x: startX, + controlsY: [startY], + targetsY: [startY + registerHeight, startY + registerHeight * 2], + label: "", + width: minGateWidth, + }; + expect(_formatGate(metadata)).toMatchSnapshot(); + }); + test("CNOT gate", () => { + const metadata: Metadata = { + type: GateType.Cnot, + x: startX, + controlsY: [startY], + targetsY: [startY + registerHeight], + label: "X", + width: minGateWidth, + }; + expect(_formatGate(metadata)).toMatchSnapshot(); + }); + test("controlled unitary gate", () => { + const metadata: Metadata = { + type: GateType.ControlledUnitary, + x: startX, + controlsY: [startY], + targetsY: [[startY + registerHeight]], + label: "U", + width: minGateWidth, + }; + expect(_formatGate(metadata)).toMatchSnapshot(); + }); + test("controlled unitary gate with arguments", () => { + const metadata: Metadata = { + type: GateType.ControlledUnitary, + x: startX, + controlsY: [startY], + targetsY: [[startY + registerHeight]], + label: "U", + displayArgs: "('foo', 'bar')", + width: 77, + }; + expect(_formatGate(metadata)).toMatchSnapshot(); + }); + test("classically controlled gate", () => { + const metadata: Metadata = { + type: GateType.ClassicalControlled, + x: startX, + controlsY: [startY + registerHeight * 2], + targetsY: [startY, startY + registerHeight], + label: "", + width: minGateWidth, + }; + expect(_formatGate(metadata)).toMatchSnapshot(); + }); + test("gate with metadata", () => { + const metadata: Metadata = { + type: GateType.Unitary, + x: startX, + controlsY: [], + targetsY: [[startY]], + label: "H", + width: minGateWidth, + dataAttributes: { a: "1", b: "2" }, + }; + expect(_formatGate(metadata)).toMatchSnapshot(); + }); + test("invalid gate", () => { + const metadata: Metadata = { + type: GateType.Invalid, + x: startX, + controlsY: [startY], + targetsY: [startY + registerHeight], + label: "Foo", + width: 48, + }; + expect(() => _formatGate(metadata)).toThrowError( + `ERROR: unknown gate (Foo) of type ${GateType.Invalid}.`, + ); + }); }); -describe('Testing formatGates', () => { - test('Single gate', () => { - const gates: Metadata[] = [ - { - type: GateType.Cnot, - x: startX, - controlsY: [startY], - targetsY: [startY + registerHeight], - label: 'X', - width: minGateWidth, - }, - ]; - expect(formatGates(gates)).toMatchSnapshot(); - }); - test('Single null gate', () => { - const gates: Metadata[] = [ - { - type: GateType.Invalid, - x: startX, - controlsY: [startY], - targetsY: [startY + registerHeight], - label: '', - width: minGateWidth, - }, - ]; - expect(() => formatGates(gates)).toThrowError(`ERROR: unknown gate () of type ${GateType.Invalid}.`); - }); - test('Multiple gates', () => { - const gates: Metadata[] = [ - { - type: GateType.Cnot, - x: startX, - controlsY: [startY + registerHeight], - targetsY: [startY], - label: 'X', - width: minGateWidth, - }, - { - type: GateType.ControlledUnitary, - x: startX, - controlsY: [startY + registerHeight], - targetsY: [[startY + registerHeight * 2]], - label: 'X', - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX, - controlsY: [], - targetsY: [[startY + registerHeight * 2]], - label: 'X', - width: minGateWidth, - }, - { - type: GateType.Measure, - x: startX, - controlsY: [startY], - targetsY: [startY + registerHeight * 3], - label: 'X', - width: minGateWidth, - }, - ]; - expect(formatGates(gates)).toMatchSnapshot(); - }); - test('Multiple gates with invalid gate', () => { - const gates: Metadata[] = [ - { - type: GateType.Unitary, - x: startX, - controlsY: [], - targetsY: [[startY + registerHeight * 2]], - label: 'X', - width: minGateWidth, - }, - { - type: GateType.Cnot, - x: startX, - controlsY: [startY + registerHeight], - targetsY: [startY], - label: 'X', - width: minGateWidth, - }, - { - type: GateType.Invalid, - x: startX, - controlsY: [], - targetsY: [startY + registerHeight * 2], - label: '', - width: minGateWidth, - }, - { - type: GateType.Invalid, - x: startX, - controlsY: [], - targetsY: [], - label: '', - width: minGateWidth, - }, - ]; - expect(() => formatGates(gates)).toThrowError(`ERROR: unknown gate () of type ${GateType.Invalid}.`); - }); +describe("Testing formatGates", () => { + test("Single gate", () => { + const gates: Metadata[] = [ + { + type: GateType.Cnot, + x: startX, + controlsY: [startY], + targetsY: [startY + registerHeight], + label: "X", + width: minGateWidth, + }, + ]; + expect(formatGates(gates)).toMatchSnapshot(); + }); + test("Single null gate", () => { + const gates: Metadata[] = [ + { + type: GateType.Invalid, + x: startX, + controlsY: [startY], + targetsY: [startY + registerHeight], + label: "", + width: minGateWidth, + }, + ]; + expect(() => formatGates(gates)).toThrowError( + `ERROR: unknown gate () of type ${GateType.Invalid}.`, + ); + }); + test("Multiple gates", () => { + const gates: Metadata[] = [ + { + type: GateType.Cnot, + x: startX, + controlsY: [startY + registerHeight], + targetsY: [startY], + label: "X", + width: minGateWidth, + }, + { + type: GateType.ControlledUnitary, + x: startX, + controlsY: [startY + registerHeight], + targetsY: [[startY + registerHeight * 2]], + label: "X", + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX, + controlsY: [], + targetsY: [[startY + registerHeight * 2]], + label: "X", + width: minGateWidth, + }, + { + type: GateType.Measure, + x: startX, + controlsY: [startY], + targetsY: [startY + registerHeight * 3], + label: "X", + width: minGateWidth, + }, + ]; + expect(formatGates(gates)).toMatchSnapshot(); + }); + test("Multiple gates with invalid gate", () => { + const gates: Metadata[] = [ + { + type: GateType.Unitary, + x: startX, + controlsY: [], + targetsY: [[startY + registerHeight * 2]], + label: "X", + width: minGateWidth, + }, + { + type: GateType.Cnot, + x: startX, + controlsY: [startY + registerHeight], + targetsY: [startY], + label: "X", + width: minGateWidth, + }, + { + type: GateType.Invalid, + x: startX, + controlsY: [], + targetsY: [startY + registerHeight * 2], + label: "", + width: minGateWidth, + }, + { + type: GateType.Invalid, + x: startX, + controlsY: [], + targetsY: [], + label: "", + width: minGateWidth, + }, + ]; + expect(() => formatGates(gates)).toThrowError( + `ERROR: unknown gate () of type ${GateType.Invalid}.`, + ); + }); }); diff --git a/circuit_vis/__tests__/inputFormatter.test.ts b/circuit_vis/__tests__/inputFormatter.test.ts index 62a04b52f0..da37a1b8f5 100644 --- a/circuit_vis/__tests__/inputFormatter.test.ts +++ b/circuit_vis/__tests__/inputFormatter.test.ts @@ -1,84 +1,102 @@ -import { Qubit } from '../src/circuit'; -import { RegisterMap, RegisterType } from '../src/register'; -import { formatInputs, _qubitInput } from '../src/formatters/inputFormatter'; -import { startY, registerHeight, classicalRegHeight } from '../src/constants'; +import { Qubit } from "../src/circuit"; +import { RegisterMap, RegisterType } from "../src/register"; +import { formatInputs, _qubitInput } from "../src/formatters/inputFormatter"; +import { startY, registerHeight, classicalRegHeight } from "../src/constants"; -describe('Testing _qubitInput', () => { - test('classical register', () => { - expect(_qubitInput(20)).toMatchSnapshot(); - expect(_qubitInput(50)).toMatchSnapshot(); - expect(_qubitInput(0)).toMatchSnapshot(); - }); +describe("Testing _qubitInput", () => { + test("classical register", () => { + expect(_qubitInput(20)).toMatchSnapshot(); + expect(_qubitInput(50)).toMatchSnapshot(); + expect(_qubitInput(0)).toMatchSnapshot(); + }); }); -describe('Testing formatInputs', () => { - test('1 quantum register', () => { - const inputs: Qubit[] = [{ id: 0 }]; - const expectedRegs: RegisterMap = { 0: { type: RegisterType.Qubit, y: startY } }; - const { qubitWires, registers } = formatInputs(inputs); - expect(qubitWires).toMatchSnapshot(); - expect(registers).toEqual(expectedRegs); - expect(registers).toEqual(expectedRegs); - }); - test('Multiple quantum registers', () => { - const inputs: Qubit[] = [{ id: 0 }, { id: 1 }, { id: 2 }]; - const expectedRegs: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, - }; - const { qubitWires, registers } = formatInputs(inputs); - expect(qubitWires).toMatchSnapshot(); - expect(registers).toEqual(expectedRegs); - expect(registers).toEqual(expectedRegs); - }); - test('Quantum and classical registers', () => { - let inputs: Qubit[] = [{ id: 0, numChildren: 1 }, { id: 1 }, { id: 2 }]; - let expectedRegs: RegisterMap = { - 0: { - type: RegisterType.Qubit, - y: startY, - children: [{ type: RegisterType.Classical, y: startY + classicalRegHeight }], - }, - 1: { type: RegisterType.Qubit, y: startY + classicalRegHeight * 2 }, - 2: { type: RegisterType.Qubit, y: startY + registerHeight + classicalRegHeight * 2 }, - }; - let { qubitWires, registers } = formatInputs(inputs); - expect(qubitWires).toMatchSnapshot(); - expect(registers).toEqual(expectedRegs); - expect(registers).toEqual(expectedRegs); +describe("Testing formatInputs", () => { + test("1 quantum register", () => { + const inputs: Qubit[] = [{ id: 0 }]; + const expectedRegs: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + }; + const { qubitWires, registers } = formatInputs(inputs); + expect(qubitWires).toMatchSnapshot(); + expect(registers).toEqual(expectedRegs); + expect(registers).toEqual(expectedRegs); + }); + test("Multiple quantum registers", () => { + const inputs: Qubit[] = [{ id: 0 }, { id: 1 }, { id: 2 }]; + const expectedRegs: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, + }; + const { qubitWires, registers } = formatInputs(inputs); + expect(qubitWires).toMatchSnapshot(); + expect(registers).toEqual(expectedRegs); + expect(registers).toEqual(expectedRegs); + }); + test("Quantum and classical registers", () => { + let inputs: Qubit[] = [{ id: 0, numChildren: 1 }, { id: 1 }, { id: 2 }]; + let expectedRegs: RegisterMap = { + 0: { + type: RegisterType.Qubit, + y: startY, + children: [ + { type: RegisterType.Classical, y: startY + classicalRegHeight }, + ], + }, + 1: { type: RegisterType.Qubit, y: startY + classicalRegHeight * 2 }, + 2: { + type: RegisterType.Qubit, + y: startY + registerHeight + classicalRegHeight * 2, + }, + }; + let { qubitWires, registers } = formatInputs(inputs); + expect(qubitWires).toMatchSnapshot(); + expect(registers).toEqual(expectedRegs); + expect(registers).toEqual(expectedRegs); - inputs = [{ id: 0 }, { id: 1, numChildren: 2 }, { id: 2, numChildren: 1 }]; - expectedRegs = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { - type: RegisterType.Qubit, - y: startY + registerHeight, - children: [ - { type: RegisterType.Classical, y: startY + registerHeight + classicalRegHeight }, - { type: RegisterType.Classical, y: startY + registerHeight + classicalRegHeight * 2 }, - ], - }, - 2: { - type: RegisterType.Qubit, - y: startY + registerHeight + classicalRegHeight * 3, - children: [{ type: RegisterType.Classical, y: startY + registerHeight + classicalRegHeight * 4 }], - }, - }; - ({ qubitWires, registers } = formatInputs(inputs)); - expect(qubitWires).toMatchSnapshot(); - expect(registers).toEqual(expectedRegs); - expect(registers).toEqual(expectedRegs); - }); - test('Skip quantum registers', () => { - const inputs: Qubit[] = [{ id: 0 }, { id: 2 }]; - const expectedRegs: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 2: { type: RegisterType.Qubit, y: startY + registerHeight }, - }; - const { qubitWires, registers } = formatInputs(inputs); - expect(qubitWires).toMatchSnapshot(); - expect(registers).toEqual(expectedRegs); - expect(registers).toEqual(expectedRegs); - }); + inputs = [{ id: 0 }, { id: 1, numChildren: 2 }, { id: 2, numChildren: 1 }]; + expectedRegs = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { + type: RegisterType.Qubit, + y: startY + registerHeight, + children: [ + { + type: RegisterType.Classical, + y: startY + registerHeight + classicalRegHeight, + }, + { + type: RegisterType.Classical, + y: startY + registerHeight + classicalRegHeight * 2, + }, + ], + }, + 2: { + type: RegisterType.Qubit, + y: startY + registerHeight + classicalRegHeight * 3, + children: [ + { + type: RegisterType.Classical, + y: startY + registerHeight + classicalRegHeight * 4, + }, + ], + }, + }; + ({ qubitWires, registers } = formatInputs(inputs)); + expect(qubitWires).toMatchSnapshot(); + expect(registers).toEqual(expectedRegs); + expect(registers).toEqual(expectedRegs); + }); + test("Skip quantum registers", () => { + const inputs: Qubit[] = [{ id: 0 }, { id: 2 }]; + const expectedRegs: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 2: { type: RegisterType.Qubit, y: startY + registerHeight }, + }; + const { qubitWires, registers } = formatInputs(inputs); + expect(qubitWires).toMatchSnapshot(); + expect(registers).toEqual(expectedRegs); + expect(registers).toEqual(expectedRegs); + }); }); diff --git a/circuit_vis/__tests__/process.test.ts b/circuit_vis/__tests__/process.test.ts index 5cd6b20c09..ff2931bd11 100644 --- a/circuit_vis/__tests__/process.test.ts +++ b/circuit_vis/__tests__/process.test.ts @@ -1,2663 +1,2877 @@ -import { Operation, ConditionalRender } from '../src/circuit'; -import { RegisterMap, RegisterType, Register } from '../src/register'; -import { Metadata, GateType } from '../src/metadata'; +import { Operation, ConditionalRender } from "../src/circuit"; +import { RegisterMap, RegisterType, Register } from "../src/register"; +import { Metadata, GateType } from "../src/metadata"; import { - processOperations, - _groupOperations, - _alignOps, - _getClassicalRegStart, - _opToMetadata, - _getRegY, - _splitTargetsY, - _fillMetadataX, - _offsetChildrenX, -} from '../src/process'; + processOperations, + _groupOperations, + _alignOps, + _getClassicalRegStart, + _opToMetadata, + _getRegY, + _splitTargetsY, + _fillMetadataX, + _offsetChildrenX, +} from "../src/process"; import { - minGateWidth, - startX, - startY, - registerHeight, - gatePadding, - classicalRegHeight, - controlBtnOffset, - groupBoxPadding, -} from '../src/constants'; + minGateWidth, + startX, + startY, + registerHeight, + gatePadding, + classicalRegHeight, + controlBtnOffset, + groupBoxPadding, +} from "../src/constants"; -describe('Testing _groupOperations', () => { +describe("Testing _groupOperations", () => { + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, + 3: { type: RegisterType.Qubit, y: startY + registerHeight * 3 }, + }; + test("single qubit gates on 1 qubit register", () => { + const operations: Operation[] = [ + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "Y", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "Z", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([ + [0, 1, 2], + [], + [], + [], + ]); + }); + test("single qubit gates on multiple qubit registers", () => { + const operations: Operation[] = [ + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "Y", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: "Z", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 2 }], + }, + { + gate: "H", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "T", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([ + [0, 3], + [1, 4], + [2], + [], + ]); + }); + test("single and multiple qubit(s) gates", () => { + let operations: Operation[] = [ + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "Y", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: "Z", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([ + [0, 1, 2], + [1], + [], + [], + ]); + operations = [ + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "Y", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "Z", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([ + [0, 1, 2], + [1], + [], + [], + ]); + operations = [ + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "Z", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "Y", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([ + [0, 1, 2], + [2], + [], + [], + ]); + operations = [ + { + gate: "Y", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "Z", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([ + [0, 1, 2], + [0], + [], + [], + ]); + operations = [ + { + gate: "Y", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "Z", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([ + [0, 1], + [0, 2], + [], + [], + ]); + }); + test("multiple qubit gates in ladder format", () => { + const operations: Operation[] = [ + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "Y", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 2 }], + }, + { + gate: "Z", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 2 }], + targets: [{ type: RegisterType.Qubit, qId: 3 }], + }, + { + gate: "H", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 2 }], + targets: [{ type: RegisterType.Qubit, qId: 3 }], + }, + { + gate: "T", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 2 }], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([ + [0, 5], + [0, 1, 4, 5], + [1, 2, 3, 4], + [2, 3], + ]); + }); + test("multiple qubit gates in ladder format with single qubit gate", () => { + let operations: Operation[] = [ + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "Y", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: "Y", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 2 }], + }, + { + gate: "Z", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 2 }], + targets: [{ type: RegisterType.Qubit, qId: 3 }], + }, + { + gate: "Z", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 2 }], + }, + { + gate: "H", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 2 }], + targets: [{ type: RegisterType.Qubit, qId: 3 }], + }, + { + gate: "T", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 2 }], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: "Y", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([ + [0, 8], + [0, 1, 2, 6, 7, 8], + [2, 3, 4, 5, 6], + [3, 5], + ]); + + operations = [ + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "Y", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: "Y", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 2 }], + }, + { + gate: "Z", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 2 }], + }, + { + gate: "T", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 2 }], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: "Y", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: "H", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "H", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "H", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "H", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([ + [0, 6, 7, 8, 9, 10], + [0, 1, 2, 4, 5, 10], + [2, 3, 4], + [], + ]); + }); + test("interleaved multiqubit gates", () => { + let operations: Operation[] = [ + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 3 }], + }, + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [{ type: RegisterType.Qubit, qId: 2 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([ + [1], + [0, 1], + [0, 1], + [0], + ]); + operations = [ + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + ], + targets: [{ type: RegisterType.Qubit, qId: 3 }], + }, + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [ + { type: RegisterType.Qubit, qId: 2 }, + { type: RegisterType.Qubit, qId: 3 }, + ], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([ + [0, 1], + [0, 1], + [0, 1], + [0, 1], + ]); + operations = [ + { + gate: "Foo", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 2 }, + { type: RegisterType.Qubit, qId: 3 }, + ], + }, + { + gate: "Bar", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + { type: RegisterType.Qubit, qId: 2 }, + ], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([ + [0, 1], + [0, 1], + [0, 1], + [0], + ]); + }); + test("classical control gates", () => { const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, - 3: { type: RegisterType.Qubit, y: startY + registerHeight * 3 }, + 0: { type: RegisterType.Qubit, y: startY }, + 1: { + type: RegisterType.Qubit, + y: startY + registerHeight, + children: [ + { + type: RegisterType.Classical, + y: startY + registerHeight + classicalRegHeight, + }, + ], + }, + 2: { + type: RegisterType.Qubit, + y: startY + registerHeight + classicalRegHeight * 2, + children: [ + { + type: RegisterType.Classical, + y: startY + registerHeight + classicalRegHeight * 3, + }, + ], + }, + 3: { + type: RegisterType.Qubit, + y: startY + registerHeight + classicalRegHeight * 4, + }, }; - test('single qubit gates on 1 qubit register', () => { - const operations: Operation[] = [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Y', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Z', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([[0, 1, 2], [], [], []]); - }); - test('single qubit gates on multiple qubit registers', () => { - const operations: Operation[] = [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Y', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: 'Z', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 2 }], - }, - { - gate: 'H', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'T', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([[0, 3], [1, 4], [2], []]); - }); - test('single and multiple qubit(s) gates', () => { - let operations: Operation[] = [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Y', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: 'Z', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([[0, 1, 2], [1], [], []]); - operations = [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Y', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Z', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([[0, 1, 2], [1], [], []]); - operations = [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Z', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Y', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([[0, 1, 2], [2], [], []]); - operations = [ - { - gate: 'Y', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Z', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([[0, 1, 2], [0], [], []]); - operations = [ - { - gate: 'Y', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Z', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([[0, 1], [0, 2], [], []]); - }); - test('multiple qubit gates in ladder format', () => { - const operations: Operation[] = [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Y', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 2 }], - }, - { - gate: 'Z', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 2 }], - targets: [{ type: RegisterType.Qubit, qId: 3 }], - }, - { - gate: 'H', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 2 }], - targets: [{ type: RegisterType.Qubit, qId: 3 }], - }, - { - gate: 'T', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 2 }], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([ - [0, 5], - [0, 1, 4, 5], - [1, 2, 3, 4], - [2, 3], - ]); - }); - test('multiple qubit gates in ladder format with single qubit gate', () => { - let operations: Operation[] = [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Y', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: 'Y', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 2 }], - }, - { - gate: 'Z', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 2 }], - targets: [{ type: RegisterType.Qubit, qId: 3 }], - }, - { - gate: 'Z', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 2 }], - }, - { - gate: 'H', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 2 }], - targets: [{ type: RegisterType.Qubit, qId: 3 }], - }, - { - gate: 'T', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 2 }], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: 'Y', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([ - [0, 8], - [0, 1, 2, 6, 7, 8], - [2, 3, 4, 5, 6], - [3, 5], - ]); - - operations = [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Y', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: 'Y', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 2 }], - }, - { - gate: 'Z', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 2 }], - }, - { - gate: 'T', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 2 }], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: 'Y', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: 'H', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'H', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'H', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'H', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([ - [0, 6, 7, 8, 9, 10], - [0, 1, 2, 4, 5, 10], - [2, 3, 4], - [], - ]); - }); - test('interleaved multiqubit gates', () => { - let operations: Operation[] = [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 3 }], - }, - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [{ type: RegisterType.Qubit, qId: 2 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([[1], [0, 1], [0, 1], [0]]); - operations = [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - ], - targets: [{ type: RegisterType.Qubit, qId: 3 }], - }, - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [ - { type: RegisterType.Qubit, qId: 2 }, - { type: RegisterType.Qubit, qId: 3 }, - ], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([ - [0, 1], - [0, 1], - [0, 1], - [0, 1], - ]); - operations = [ - { - gate: 'Foo', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 2 }, - { type: RegisterType.Qubit, qId: 3 }, - ], - }, - { - gate: 'Bar', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - { type: RegisterType.Qubit, qId: 2 }, - ], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([[0, 1], [0, 1], [0, 1], [0]]); - }); - test('classical control gates', () => { - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { - type: RegisterType.Qubit, - y: startY + registerHeight, - children: [{ type: RegisterType.Classical, y: startY + registerHeight + classicalRegHeight }], - }, - 2: { - type: RegisterType.Qubit, - y: startY + registerHeight + classicalRegHeight * 2, - children: [{ type: RegisterType.Classical, y: startY + registerHeight + classicalRegHeight * 3 }], - }, - 3: { type: RegisterType.Qubit, y: startY + registerHeight + classicalRegHeight * 4 }, - }; - let operations: Operation[] = [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Classical, qId: 2, cId: 0 }], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([[0, 1], [0], [0], [0]]); - operations = [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Classical, qId: 2, cId: 0 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([[0], [0, 1], [0], [0]]); - operations = [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Classical, qId: 1, cId: 0 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([[1], [0, 1], [1], [1]]); - }); - test('skipped registers', () => { - let operations: Operation[] = [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Z', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 2 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([[0], [], [1], []]); - operations = [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Z', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 2 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([[0], [0, 1], [1], []]); - }); - test('no qubits', () => { - const operations: Operation[] = [ - { - gate: 'NoOp1', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [], - }, - { - gate: 'NoOp2', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([[], [], [], []]); - }); - test('empty arguments', () => { - expect(_groupOperations([], {})).toEqual([]); - }); + let operations: Operation[] = [ + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Classical, qId: 2, cId: 0 }], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([ + [0, 1], + [0], + [0], + [0], + ]); + operations = [ + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Classical, qId: 2, cId: 0 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([ + [0], + [0, 1], + [0], + [0], + ]); + operations = [ + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Classical, qId: 1, cId: 0 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([ + [1], + [0, 1], + [1], + [1], + ]); + }); + test("skipped registers", () => { + let operations: Operation[] = [ + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "Z", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 2 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([[0], [], [1], []]); + operations = [ + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "Z", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 2 }], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([ + [0], + [0, 1], + [1], + [], + ]); + }); + test("no qubits", () => { + const operations: Operation[] = [ + { + gate: "NoOp1", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [], + }, + { + gate: "NoOp2", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [], + }, + ]; + expect(_groupOperations(operations, registers)).toEqual([[], [], [], []]); + }); + test("empty arguments", () => { + expect(_groupOperations([], {})).toEqual([]); + }); }); -describe('Testing _alignOps', () => { - test('single qubit gates', () => { - const ops: number[][] = [ - [0, 2, 5, 6], - [1, 3, 4], - ]; - expect(_alignOps(ops)).toEqual(ops); - }); - test('correct ordering of single qubit gate after multiqubit gate', () => { - const ops: number[][] = [ - [0, 1, 3], - [1, 2], - ]; - expect(_alignOps(ops)).toEqual([ - [0, 1, 3], - [null, 1, 2], - ]); - }); - test('padding of multiqubit register after single qubit gate', () => { - const ops: number[][] = [[1], [0, 1]]; - expect(_alignOps(ops)).toEqual([ - [null, 1], - [0, 1], - ]); - }); - test('no padding of single qubit gate after multiqubit gate on different registers', () => { - const ops: number[][] = [[0, 3], [2], [1, 2]]; - expect(_alignOps(ops)).toEqual([ - [0, 3], - [null, 2], - [1, 2], - ]); - }); - test('ladder of cnots', () => { - const ops: number[][] = [ - [0, 4], - [0, 1, 3, 4], - [1, 2, 3], - ]; - expect(_alignOps(ops)).toEqual([ - [0, null, null, null, 4], - [0, 1, null, 3, 4], - [null, 1, 2, 3], - ]); - }); - test('interleaved multiqubit gates', () => { - let ops: number[][] = [[0], [0, 1], [0, 1], [1]]; - expect(_alignOps(ops)).toEqual([[0], [0, 1], [0, 1], [null, 1]]); - ops = [[0], [0], [0, 1], [1], [1], [1]]; - expect(_alignOps(ops)).toEqual([[0], [0], [0, 1], [null, 1], [null, 1], [null, 1]]); - }); - test('skipped registers', () => { - let ops: number[][] = [[0], [], [1], []]; - expect(_alignOps(ops)).toEqual([[0], [], [1], []]); - ops = [[0], [], [1, 2], [2]]; - expect(_alignOps(ops)).toEqual([[0], [], [1, 2], [null, 2]]); - }); - test('no ops', () => { - expect(_alignOps([])).toEqual([]); - }); +describe("Testing _alignOps", () => { + test("single qubit gates", () => { + const ops: number[][] = [ + [0, 2, 5, 6], + [1, 3, 4], + ]; + expect(_alignOps(ops)).toEqual(ops); + }); + test("correct ordering of single qubit gate after multiqubit gate", () => { + const ops: number[][] = [ + [0, 1, 3], + [1, 2], + ]; + expect(_alignOps(ops)).toEqual([ + [0, 1, 3], + [null, 1, 2], + ]); + }); + test("padding of multiqubit register after single qubit gate", () => { + const ops: number[][] = [[1], [0, 1]]; + expect(_alignOps(ops)).toEqual([ + [null, 1], + [0, 1], + ]); + }); + test("no padding of single qubit gate after multiqubit gate on different registers", () => { + const ops: number[][] = [[0, 3], [2], [1, 2]]; + expect(_alignOps(ops)).toEqual([ + [0, 3], + [null, 2], + [1, 2], + ]); + }); + test("ladder of cnots", () => { + const ops: number[][] = [ + [0, 4], + [0, 1, 3, 4], + [1, 2, 3], + ]; + expect(_alignOps(ops)).toEqual([ + [0, null, null, null, 4], + [0, 1, null, 3, 4], + [null, 1, 2, 3], + ]); + }); + test("interleaved multiqubit gates", () => { + let ops: number[][] = [[0], [0, 1], [0, 1], [1]]; + expect(_alignOps(ops)).toEqual([[0], [0, 1], [0, 1], [null, 1]]); + ops = [[0], [0], [0, 1], [1], [1], [1]]; + expect(_alignOps(ops)).toEqual([ + [0], + [0], + [0, 1], + [null, 1], + [null, 1], + [null, 1], + ]); + }); + test("skipped registers", () => { + let ops: number[][] = [[0], [], [1], []]; + expect(_alignOps(ops)).toEqual([[0], [], [1], []]); + ops = [[0], [], [1, 2], [2]]; + expect(_alignOps(ops)).toEqual([[0], [], [1, 2], [null, 2]]); + }); + test("no ops", () => { + expect(_alignOps([])).toEqual([]); + }); }); -describe('Testing _getClassicalRegStart', () => { - test('no measurement gates', () => { - const ops: Operation[] = [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Y', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ]; - const idxList: number[][] = [[0, 1]]; - expect(_getClassicalRegStart(ops, idxList)).toEqual([]); - }); - test('one measurement gate', () => { - const ops: Operation[] = [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'M', - isMeasurement: true, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], - }, - ]; - const idxList: number[][] = [[0, 1]]; - expect(_getClassicalRegStart(ops, idxList)).toEqual([[1, { type: RegisterType.Classical, qId: 0, cId: 0 }]]); - }); - test('multiple measurement gates', () => { - const ops: Operation[] = [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'M', - isMeasurement: true, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Classical, qId: 1, cId: 0 }], - }, - { - gate: 'M', - isMeasurement: true, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], - }, - { - gate: 'M', - isMeasurement: true, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], - }, - ]; - const idxList: number[][] = [[0, 2, 3], [1]]; - const clsRegs: [number, Register][] = [ - [1, { type: RegisterType.Classical, qId: 0, cId: 0 }], - [2, { type: RegisterType.Classical, qId: 0, cId: 0 }], - [0, { type: RegisterType.Classical, qId: 1, cId: 0 }], - ]; - expect(_getClassicalRegStart(ops, idxList)).toEqual(clsRegs); - }); +describe("Testing _getClassicalRegStart", () => { + test("no measurement gates", () => { + const ops: Operation[] = [ + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "Y", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ]; + const idxList: number[][] = [[0, 1]]; + expect(_getClassicalRegStart(ops, idxList)).toEqual([]); + }); + test("one measurement gate", () => { + const ops: Operation[] = [ + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "M", + isMeasurement: true, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], + }, + ]; + const idxList: number[][] = [[0, 1]]; + expect(_getClassicalRegStart(ops, idxList)).toEqual([ + [1, { type: RegisterType.Classical, qId: 0, cId: 0 }], + ]); + }); + test("multiple measurement gates", () => { + const ops: Operation[] = [ + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "M", + isMeasurement: true, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Classical, qId: 1, cId: 0 }], + }, + { + gate: "M", + isMeasurement: true, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], + }, + { + gate: "M", + isMeasurement: true, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], + }, + ]; + const idxList: number[][] = [[0, 2, 3], [1]]; + const clsRegs: [number, Register][] = [ + [1, { type: RegisterType.Classical, qId: 0, cId: 0 }], + [2, { type: RegisterType.Classical, qId: 0, cId: 0 }], + [0, { type: RegisterType.Classical, qId: 1, cId: 0 }], + ]; + expect(_getClassicalRegStart(ops, idxList)).toEqual(clsRegs); + }); }); -describe('Testing _opToMetadata', () => { - test('single qubit gate', () => { - const op: Operation = { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - }; - const metadata: Metadata = { - type: GateType.X, - x: 0, - controlsY: [], - targetsY: [startY + registerHeight], - label: 'X', - width: minGateWidth, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); - test('isAdjoint gate', () => { - const op: Operation = { - gate: 'Foo', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: true, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - }; - const metadata: Metadata = { - type: GateType.Unitary, - x: 0, - controlsY: [], - targetsY: [startY + registerHeight], - label: "Foo'", - width: 48, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); - test('measure gate', () => { - const op: Operation = { - gate: 'M', - isMeasurement: true, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], - }; - const registers: RegisterMap = { - 0: { - type: RegisterType.Qubit, - y: startY, - children: [{ type: RegisterType.Classical, y: startY + classicalRegHeight }], - }, - }; - const metadata: Metadata = { - type: GateType.Measure, - x: 0, - controlsY: [startY], - targetsY: [startY + classicalRegHeight], - label: '', - width: minGateWidth, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); - test('swap gate', () => { - const op: Operation = { - gate: 'SWAP', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - ], - }; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - }; - const metadata: Metadata = { - type: GateType.Swap, - x: 0, - controlsY: [], - targetsY: [startY, startY + registerHeight], - label: '', - width: minGateWidth, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); - test('isControlled swap gate', () => { - const op: Operation = { - gate: 'SWAP', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [ - { type: RegisterType.Qubit, qId: 1 }, - { type: RegisterType.Qubit, qId: 2 }, - ], - }; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, - }; - const metadata: Metadata = { - type: GateType.Swap, - x: 0, - controlsY: [startY], - targetsY: [startY + registerHeight, startY + registerHeight * 2], - label: '', - width: minGateWidth, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); - test('single qubit unitary gate', () => { - const op: Operation = { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - }; - const metadata: Metadata = { +describe("Testing _opToMetadata", () => { + test("single qubit gate", () => { + const op: Operation = { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + }; + const metadata: Metadata = { + type: GateType.X, + x: 0, + controlsY: [], + targetsY: [startY + registerHeight], + label: "X", + width: minGateWidth, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); + test("isAdjoint gate", () => { + const op: Operation = { + gate: "Foo", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: true, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + }; + const metadata: Metadata = { + type: GateType.Unitary, + x: 0, + controlsY: [], + targetsY: [startY + registerHeight], + label: "Foo'", + width: 48, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); + test("measure gate", () => { + const op: Operation = { + gate: "M", + isMeasurement: true, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], + }; + const registers: RegisterMap = { + 0: { + type: RegisterType.Qubit, + y: startY, + children: [ + { type: RegisterType.Classical, y: startY + classicalRegHeight }, + ], + }, + }; + const metadata: Metadata = { + type: GateType.Measure, + x: 0, + controlsY: [startY], + targetsY: [startY + classicalRegHeight], + label: "", + width: minGateWidth, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); + test("swap gate", () => { + const op: Operation = { + gate: "SWAP", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + ], + }; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + }; + const metadata: Metadata = { + type: GateType.Swap, + x: 0, + controlsY: [], + targetsY: [startY, startY + registerHeight], + label: "", + width: minGateWidth, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); + test("isControlled swap gate", () => { + const op: Operation = { + gate: "SWAP", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [ + { type: RegisterType.Qubit, qId: 1 }, + { type: RegisterType.Qubit, qId: 2 }, + ], + }; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, + }; + const metadata: Metadata = { + type: GateType.Swap, + x: 0, + controlsY: [startY], + targetsY: [startY + registerHeight, startY + registerHeight * 2], + label: "", + width: minGateWidth, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); + test("single qubit unitary gate", () => { + const op: Operation = { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + }; + const metadata: Metadata = { + type: GateType.X, + x: 0, + controlsY: [], + targetsY: [startY], + label: "X", + width: minGateWidth, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); + test("multiqubit unitary gate", () => { + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, + }; + let op: Operation = { + gate: "ZZ", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + ], + }; + let metadata: Metadata = { + type: GateType.Unitary, + x: 0, + controlsY: [], + targetsY: [startY, startY + registerHeight], + label: "ZZ", + width: minGateWidth, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + op = { + gate: "XX", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [ + { type: RegisterType.Qubit, qId: 1 }, + { type: RegisterType.Qubit, qId: 2 }, + ], + }; + metadata = { + type: GateType.Unitary, + x: 0, + controlsY: [], + targetsY: [startY + registerHeight, startY + registerHeight * 2], + label: "XX", + width: minGateWidth, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); + test("isControlled unitary gates", () => { + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, + 3: { type: RegisterType.Qubit, y: startY + registerHeight * 3 }, + }; + let op: Operation = { + gate: "ZZ", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }; + let metadata: Metadata = { + type: GateType.ControlledUnitary, + x: 0, + controlsY: [startY + registerHeight], + targetsY: [startY], + label: "ZZ", + width: minGateWidth, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + op = { + gate: "XX", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [ + { type: RegisterType.Qubit, qId: 1 }, + { type: RegisterType.Qubit, qId: 2 }, + ], + }; + metadata = { + type: GateType.ControlledUnitary, + x: 0, + controlsY: [startY], + targetsY: [startY + registerHeight, startY + registerHeight * 2], + label: "XX", + width: minGateWidth, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + op = { + gate: "Foo", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [ + { type: RegisterType.Qubit, qId: 2 }, + { type: RegisterType.Qubit, qId: 3 }, + ], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + ], + }; + metadata = { + type: GateType.ControlledUnitary, + label: "Foo", + x: 0, + controlsY: [startY + registerHeight * 2, startY + registerHeight * 3], + targetsY: [startY, startY + registerHeight], + width: 45, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); + test("single-qubit unitary gates with arguments", () => { + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + }; + let op: Operation = { + gate: "RX", + displayArgs: "(0.25)", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }; + let metadata: Metadata = { + type: GateType.Unitary, + x: 0, + controlsY: [], + targetsY: [startY], + label: "RX", + displayArgs: "(0.25)", + width: 52, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + + // Test long argument + op = { + gate: "RX", + displayArgs: "(0.25, 1.0, 'foobar', (3.14, 6.67))", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }; + metadata = { + type: GateType.Unitary, + x: 0, + controlsY: [], + targetsY: [startY], + label: "RX", + displayArgs: "(0.25, 1.0, 'foobar', (3.14, 6.67))", + width: 188, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + + // Test isControlled + op = { + gate: "RX", + displayArgs: "(0.25)", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }; + metadata = { + type: GateType.ControlledUnitary, + x: 0, + controlsY: [startY + registerHeight], + targetsY: [startY], + label: "RX", + displayArgs: "(0.25)", + width: 52, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); + test("multi-qubit unitary gates with arguments", () => { + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, + }; + let op: Operation = { + gate: "U", + displayArgs: "('foo', 'bar')", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + ], + }; + let metadata: Metadata = { + type: GateType.Unitary, + x: 0, + controlsY: [], + targetsY: [startY, startY + registerHeight], + label: "U", + displayArgs: "('foo', 'bar')", + width: 77, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + + // Test long argument + op = { + gate: "U", + displayArgs: "(0.25, 1.0, 'foobar', (3.14, 6.67))", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + ], + }; + metadata = { + type: GateType.Unitary, + x: 0, + controlsY: [], + targetsY: [startY, startY + registerHeight], + label: "U", + displayArgs: "(0.25, 1.0, 'foobar', (3.14, 6.67))", + width: 188, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + + // Test isControlled + op = { + gate: "U", + displayArgs: "('foo', 'bar')", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 2 }, + ], + }; + metadata = { + type: GateType.ControlledUnitary, + x: 0, + controlsY: [startY + registerHeight], + targetsY: [startY, startY + registerHeight * 2], + label: "U", + displayArgs: "('foo', 'bar')", + width: 77, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); + test("classically-controlled gates", () => { + const op: Operation = { + gate: "X", + isMeasurement: false, + isConditional: true, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + ], + children: [ + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + conditionalRender: ConditionalRender.OnZero, + }, + { + gate: "H", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + conditionalRender: ConditionalRender.OnOne, + }, + ], + }; + const registers: RegisterMap = { + 0: { + type: RegisterType.Qubit, + y: startY, + children: [ + { type: RegisterType.Classical, y: startY + classicalRegHeight }, + ], + }, + 1: { type: RegisterType.Qubit, y: startY + classicalRegHeight * 2 }, + }; + const metadata: Metadata = { + type: GateType.ClassicalControlled, + x: 0, + controlsY: [startY + classicalRegHeight], + targetsY: [startY, startY + classicalRegHeight * 2], + label: "", + width: minGateWidth + controlBtnOffset + groupBoxPadding * 2, + children: [ + [ + { type: GateType.X, - x: 0, + x: startX + minGateWidth / 2, controlsY: [], targetsY: [startY], - label: 'X', + label: "X", width: minGateWidth, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); - test('multiqubit unitary gate', () => { - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, - }; - let op: Operation = { - gate: 'ZZ', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - ], - }; - let metadata: Metadata = { + }, + ], + [ + { type: GateType.Unitary, - x: 0, + x: startX + minGateWidth / 2, controlsY: [], - targetsY: [startY, startY + registerHeight], - label: 'ZZ', - width: minGateWidth, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - op = { - gate: 'XX', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [ - { type: RegisterType.Qubit, qId: 1 }, - { type: RegisterType.Qubit, qId: 2 }, - ], - }; - metadata = { - type: GateType.Unitary, - x: 0, - controlsY: [], - targetsY: [startY + registerHeight, startY + registerHeight * 2], - label: 'XX', - width: minGateWidth, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); - test('isControlled unitary gates', () => { - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, - 3: { type: RegisterType.Qubit, y: startY + registerHeight * 3 }, - }; - let op: Operation = { - gate: 'ZZ', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }; - let metadata: Metadata = { - type: GateType.ControlledUnitary, - x: 0, - controlsY: [startY + registerHeight], - targetsY: [startY], - label: 'ZZ', - width: minGateWidth, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - op = { - gate: 'XX', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [ - { type: RegisterType.Qubit, qId: 1 }, - { type: RegisterType.Qubit, qId: 2 }, - ], - }; - metadata = { - type: GateType.ControlledUnitary, - x: 0, - controlsY: [startY], - targetsY: [startY + registerHeight, startY + registerHeight * 2], - label: 'XX', + targetsY: [[startY + classicalRegHeight * 2]], + label: "H", width: minGateWidth, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - op = { - gate: 'Foo', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [ - { type: RegisterType.Qubit, qId: 2 }, - { type: RegisterType.Qubit, qId: 3 }, - ], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - ], - }; - metadata = { - type: GateType.ControlledUnitary, - label: 'Foo', - x: 0, - controlsY: [startY + registerHeight * 2, startY + registerHeight * 3], - targetsY: [startY, startY + registerHeight], - width: 45, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); - test('single-qubit unitary gates with arguments', () => { - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - }; - let op: Operation = { - gate: 'RX', - displayArgs: '(0.25)', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }; - let metadata: Metadata = { - type: GateType.Unitary, - x: 0, - controlsY: [], - targetsY: [startY], - label: 'RX', - displayArgs: '(0.25)', - width: 52, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - - // Test long argument - op = { - gate: 'RX', - displayArgs: "(0.25, 1.0, 'foobar', (3.14, 6.67))", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }; - metadata = { - type: GateType.Unitary, - x: 0, - controlsY: [], - targetsY: [startY], - label: 'RX', - displayArgs: "(0.25, 1.0, 'foobar', (3.14, 6.67))", - width: 188, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - - // Test isControlled - op = { - gate: 'RX', - displayArgs: '(0.25)', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }; - metadata = { - type: GateType.ControlledUnitary, - x: 0, - controlsY: [startY + registerHeight], - targetsY: [startY], - label: 'RX', - displayArgs: '(0.25)', - width: 52, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); - test('multi-qubit unitary gates with arguments', () => { - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, - }; - let op: Operation = { - gate: 'U', - displayArgs: "('foo', 'bar')", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - ], - }; - let metadata: Metadata = { - type: GateType.Unitary, - x: 0, - controlsY: [], - targetsY: [startY, startY + registerHeight], - label: 'U', - displayArgs: "('foo', 'bar')", - width: 77, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - - // Test long argument - op = { - gate: 'U', - displayArgs: "(0.25, 1.0, 'foobar', (3.14, 6.67))", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - ], - }; - metadata = { - type: GateType.Unitary, - x: 0, - controlsY: [], - targetsY: [startY, startY + registerHeight], - label: 'U', - displayArgs: "(0.25, 1.0, 'foobar', (3.14, 6.67))", - width: 188, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - - // Test isControlled - op = { - gate: 'U', - displayArgs: "('foo', 'bar')", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 2 }, - ], - }; - metadata = { - type: GateType.ControlledUnitary, - x: 0, - controlsY: [startY + registerHeight], - targetsY: [startY, startY + registerHeight * 2], - label: 'U', - displayArgs: "('foo', 'bar')", - width: 77, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); - test('classically-controlled gates', () => { - const op: Operation = { - gate: 'X', - isMeasurement: false, - isConditional: true, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - ], - children: [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - conditionalRender: ConditionalRender.OnZero, - }, - { - gate: 'H', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - conditionalRender: ConditionalRender.OnOne, - }, - ], - }; - const registers: RegisterMap = { - 0: { - type: RegisterType.Qubit, - y: startY, - children: [{ type: RegisterType.Classical, y: startY + classicalRegHeight }], - }, - 1: { type: RegisterType.Qubit, y: startY + classicalRegHeight * 2 }, - }; - const metadata: Metadata = { - type: GateType.ClassicalControlled, - x: 0, - controlsY: [startY + classicalRegHeight], - targetsY: [startY, startY + classicalRegHeight * 2], - label: '', - width: minGateWidth + controlBtnOffset + groupBoxPadding * 2, - children: [ - [ - { - type: GateType.X, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [startY], - label: 'X', - width: minGateWidth, - }, - ], - [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [[startY + classicalRegHeight * 2]], - label: 'H', - width: minGateWidth, - }, - ], - ], - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); - test('grouped gates', () => { - const op: Operation = { - gate: 'Foo', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - conditionalRender: ConditionalRender.AsGroup, - controls: [], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - ], - children: [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - conditionalRender: ConditionalRender.OnZero, - }, - { - gate: 'H', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - conditionalRender: ConditionalRender.OnOne, - }, - ], - }; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - }; - const metadata: Metadata = { - type: GateType.Group, - x: 0, - controlsY: [], - targetsY: [startY, startY + registerHeight], - label: '', - width: minGateWidth + groupBoxPadding * 2, - dataAttributes: { expanded: 'true' }, - children: [ - { - type: GateType.X, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [startY], - label: 'X', - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [[startY + registerHeight]], - label: 'H', - width: minGateWidth, - }, - ], - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); - test('no render on null', () => { - const metadata: Metadata = { - type: GateType.Invalid, - x: 0, - controlsY: [], - targetsY: [], - label: '', - width: -1, - }; - expect(_opToMetadata(null, [])).toEqual(metadata); - }); - test('Invalid register', () => { - let op: Operation = { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - }; - expect(() => _opToMetadata(op, registers)).toThrowError('ERROR: Qubit register with ID 1 not found.'); + }, + ], + ], + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); + test("grouped gates", () => { + const op: Operation = { + gate: "Foo", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + conditionalRender: ConditionalRender.AsGroup, + controls: [], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + ], + children: [ + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + conditionalRender: ConditionalRender.OnZero, + }, + { + gate: "H", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + conditionalRender: ConditionalRender.OnOne, + }, + ], + }; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + }; + const metadata: Metadata = { + type: GateType.Group, + x: 0, + controlsY: [], + targetsY: [startY, startY + registerHeight], + label: "", + width: minGateWidth + groupBoxPadding * 2, + dataAttributes: { expanded: "true" }, + children: [ + { + type: GateType.X, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [startY], + label: "X", + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [[startY + registerHeight]], + label: "H", + width: minGateWidth, + }, + ], + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); + test("no render on null", () => { + const metadata: Metadata = { + type: GateType.Invalid, + x: 0, + controlsY: [], + targetsY: [], + label: "", + width: -1, + }; + expect(_opToMetadata(null, [])).toEqual(metadata); + }); + test("Invalid register", () => { + let op: Operation = { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + }; + expect(() => _opToMetadata(op, registers)).toThrowError( + "ERROR: Qubit register with ID 1 not found.", + ); - op = { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [{ type: RegisterType.Classical, qId: 0, cId: 2 }], - targets: [], - }; - expect(() => _opToMetadata(op, registers)).toThrowError('ERROR: No classical registers found for qubit ID 0.'); - }); - test('skipped registers', () => { - const op: Operation = { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 2 }], - }; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 2: { type: RegisterType.Qubit, y: startY + registerHeight }, - }; - const metadata: Metadata = { - type: GateType.X, - x: 0, - controlsY: [], - targetsY: [startY + registerHeight], - label: 'X', - width: minGateWidth, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); + op = { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [{ type: RegisterType.Classical, qId: 0, cId: 2 }], + targets: [], + }; + expect(() => _opToMetadata(op, registers)).toThrowError( + "ERROR: No classical registers found for qubit ID 0.", + ); + }); + test("skipped registers", () => { + const op: Operation = { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 2 }], + }; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 2: { type: RegisterType.Qubit, y: startY + registerHeight }, + }; + const metadata: Metadata = { + type: GateType.X, + x: 0, + controlsY: [], + targetsY: [startY + registerHeight], + label: "X", + width: minGateWidth, + }; + expect(_opToMetadata(op, registers)).toEqual(metadata); + }); }); -describe('Testing _getRegY', () => { +describe("Testing _getRegY", () => { + const registers: RegisterMap = { + 0: { + type: RegisterType.Qubit, + y: startY, + children: [ + { type: RegisterType.Classical, y: startY + classicalRegHeight }, + ], + }, + }; + test("quantum register", () => { + const reg: Register = { type: RegisterType.Qubit, qId: 0 }; + expect(_getRegY(reg, registers)).toEqual(startY); + }); + test("classical register", () => { + const reg: Register = { type: RegisterType.Classical, qId: 0, cId: 0 }; + expect(_getRegY(reg, registers)).toEqual(startY + classicalRegHeight); + }); + test("No children", () => { const registers: RegisterMap = { - 0: { - type: RegisterType.Qubit, - y: startY, - children: [{ type: RegisterType.Classical, y: startY + classicalRegHeight }], - }, + 0: { type: RegisterType.Qubit, y: startY }, }; - test('quantum register', () => { - const reg: Register = { type: RegisterType.Qubit, qId: 0 }; - expect(_getRegY(reg, registers)).toEqual(startY); - }); - test('classical register', () => { - const reg: Register = { type: RegisterType.Classical, qId: 0, cId: 0 }; - expect(_getRegY(reg, registers)).toEqual(startY + classicalRegHeight); - }); - test('No children', () => { - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - }; - const reg: Register = { type: RegisterType.Classical, qId: 0, cId: 0 }; - expect(() => _getRegY(reg, registers)).toThrowError('ERROR: No classical registers found for qubit ID 0.'); - }); - test('Null cId', () => { - const reg: Register = { type: RegisterType.Classical, qId: 0 }; - expect(() => _getRegY(reg, registers)).toThrowError( - 'ERROR: No ID defined for classical register associated with qubit ID 0.', - ); - }); - test('Invalid cId', () => { - const reg: Register = { type: RegisterType.Classical, qId: 0, cId: 1 }; - expect(() => _getRegY(reg, registers)).toThrowError( - 'ERROR: Classical register ID 1 invalid for qubit ID 0 with 1 classical register(s).', - ); - }); - test('Invalid register type', () => { - const reg: Register = { type: 2, qId: 0, cId: 1 }; - expect(() => _getRegY(reg, registers)).toThrowError('ERROR: Unknown register type 2.'); - }); + const reg: Register = { type: RegisterType.Classical, qId: 0, cId: 0 }; + expect(() => _getRegY(reg, registers)).toThrowError( + "ERROR: No classical registers found for qubit ID 0.", + ); + }); + test("Null cId", () => { + const reg: Register = { type: RegisterType.Classical, qId: 0 }; + expect(() => _getRegY(reg, registers)).toThrowError( + "ERROR: No ID defined for classical register associated with qubit ID 0.", + ); + }); + test("Invalid cId", () => { + const reg: Register = { type: RegisterType.Classical, qId: 0, cId: 1 }; + expect(() => _getRegY(reg, registers)).toThrowError( + "ERROR: Classical register ID 1 invalid for qubit ID 0 with 1 classical register(s).", + ); + }); + test("Invalid register type", () => { + const reg: Register = { type: 2, qId: 0, cId: 1 }; + expect(() => _getRegY(reg, registers)).toThrowError( + "ERROR: Unknown register type 2.", + ); + }); }); -describe('Testing _splitTargetsY', () => { - const registers: RegisterMap = { - 0: { - type: RegisterType.Qubit, - y: startY, +describe("Testing _splitTargetsY", () => { + const registers: RegisterMap = { + 0: { + type: RegisterType.Qubit, + y: startY, + }, + 1: { + type: RegisterType.Qubit, + y: startY + registerHeight, + children: [ + { + type: RegisterType.Classical, + y: startY + registerHeight + classicalRegHeight, }, - 1: { - type: RegisterType.Qubit, - y: startY + registerHeight, - children: [{ type: RegisterType.Classical, y: startY + registerHeight + classicalRegHeight }], + ], + }, + 2: { + type: RegisterType.Qubit, + y: startY + registerHeight * 2 + classicalRegHeight, + children: [ + { + type: RegisterType.Classical, + y: startY + registerHeight * 2 + classicalRegHeight * 2, }, - 2: { - type: RegisterType.Qubit, - y: startY + registerHeight * 2 + classicalRegHeight, - children: [ - { type: RegisterType.Classical, y: startY + registerHeight * 2 + classicalRegHeight * 2 }, - { type: RegisterType.Classical, y: startY + registerHeight * 2 + classicalRegHeight * 3 }, - { type: RegisterType.Classical, y: startY + registerHeight * 2 + classicalRegHeight * 4 }, - ], + { + type: RegisterType.Classical, + y: startY + registerHeight * 2 + classicalRegHeight * 3, }, - }; - test('adjacent qubit regs', () => { - const targets: Register[] = [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 2 }, - { type: RegisterType.Qubit, qId: 1 }, - ]; - const targetsY: number[] = [startY, startY + registerHeight, startY + registerHeight * 2 + classicalRegHeight]; - expect(_splitTargetsY(targets, [], registers)).toEqual([targetsY]); - expect(_splitTargetsY(targets, [0], registers)).toEqual([targetsY]); - expect(_splitTargetsY(targets, [startY + registerHeight * 3], registers)).toEqual([targetsY]); - expect(_splitTargetsY(targets, [0, startY + registerHeight * 3], registers)).toEqual([targetsY]); - }); - test('adjacent classical regs', () => { - const targets: Register[] = [ - { type: RegisterType.Classical, qId: 2, cId: 0 }, - { type: RegisterType.Classical, qId: 2, cId: 2 }, - { type: RegisterType.Classical, qId: 2, cId: 1 }, - ]; - const targetsY: number[] = [ - startY + registerHeight * 2 + classicalRegHeight * 2, - startY + registerHeight * 2 + classicalRegHeight * 3, - startY + registerHeight * 2 + classicalRegHeight * 4, - ]; - expect(_splitTargetsY(targets, [], registers)).toEqual([targetsY]); - expect(_splitTargetsY(targets, [0], registers)).toEqual([targetsY]); - expect(_splitTargetsY(targets, [startY + registerHeight * 3 + classicalRegHeight * 4], registers)).toEqual([ - targetsY, - ]); - expect(_splitTargetsY(targets, [0, startY + registerHeight * 3 + classicalRegHeight * 4], registers)).toEqual([ - targetsY, - ]); - }); - test('adjacent qubit/classical regs', () => { - const targets: Register[] = [ - { type: RegisterType.Qubit, qId: 2 }, - { type: RegisterType.Classical, qId: 1, cId: 0 }, - { type: RegisterType.Classical, qId: 2, cId: 0 }, - ]; - const targetsY: number[] = [ - startY + registerHeight + classicalRegHeight, - startY + registerHeight * 2 + classicalRegHeight, - startY + registerHeight * 2 + classicalRegHeight * 2, - ]; - expect(_splitTargetsY(targets, [], registers)).toEqual([targetsY]); - expect(_splitTargetsY(targets, [0], registers)).toEqual([targetsY]); - expect(_splitTargetsY(targets, [startY + registerHeight * 3 + classicalRegHeight * 4], registers)).toEqual([ - targetsY, - ]); - expect(_splitTargetsY(targets, [0, startY + registerHeight * 3 + classicalRegHeight * 4], registers)).toEqual([ - targetsY, - ]); - }); - test('single target', () => { - const targets: Register[] = [{ type: RegisterType.Qubit, qId: 0 }]; - expect(_splitTargetsY(targets, [], registers)).toEqual([[startY]]); - expect(_splitTargetsY(targets, [0], registers)).toEqual([[startY]]); - expect(_splitTargetsY(targets, [startY + registerHeight], registers)).toEqual([[startY]]); - expect(_splitTargetsY(targets, [0, startY + registerHeight], registers)).toEqual([[startY]]); - }); - test('split non-adjacent qubit regs', () => { - const targets: Register[] = [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 2 }, - ]; - const targetsY: number[][] = [[startY], [startY + registerHeight * 2 + classicalRegHeight]]; - expect(_splitTargetsY(targets, [], registers)).toEqual(targetsY); - expect(_splitTargetsY(targets, [0], registers)).toEqual(targetsY); - expect(_splitTargetsY(targets, [startY + registerHeight * 3], registers)).toEqual(targetsY); - expect(_splitTargetsY(targets, [0, startY + registerHeight * 3], registers)).toEqual(targetsY); - }); - test('split two qubit regs with classical register', () => { - const targets: Register[] = [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - ]; - const targetsY: number[][] = [[startY], [startY + registerHeight]]; - expect(_splitTargetsY(targets, [startY + classicalRegHeight], registers)).toEqual(targetsY); - expect(_splitTargetsY(targets, [0, startY + classicalRegHeight], registers)).toEqual(targetsY); - expect(_splitTargetsY(targets, [startY + registerHeight * 2, startY + classicalRegHeight], registers)).toEqual( - targetsY, - ); - expect( - _splitTargetsY(targets, [startY + registerHeight * 2, 0, startY + classicalRegHeight], registers), - ).toEqual(targetsY); - }); - test('split two classical regs with classical reg', () => { - const targets: Register[] = [ - { type: RegisterType.Classical, qId: 2, cId: 0 }, - { type: RegisterType.Classical, qId: 2, cId: 2 }, - ]; - const targetsY: number[][] = [ - [startY + registerHeight * 2 + classicalRegHeight * 2], - [startY + registerHeight * 2 + classicalRegHeight * 4], - ]; - expect(_splitTargetsY(targets, [startY + registerHeight * 2 + classicalRegHeight * 3], registers)).toEqual( - targetsY, - ); - expect(_splitTargetsY(targets, [0, startY + registerHeight * 2 + classicalRegHeight * 3], registers)).toEqual( - targetsY, - ); - expect( - _splitTargetsY( - targets, - [ - startY + registerHeight * 3 + classicalRegHeight * 2, - startY + registerHeight * 2 + classicalRegHeight * 3, - ], - registers, - ), - ).toEqual(targetsY); - expect( - _splitTargetsY( - targets, - [ - startY + registerHeight * 3 + classicalRegHeight * 2, - 0, - startY + registerHeight * 2 + classicalRegHeight * 3, - ], - registers, - ), - ).toEqual(targetsY); - }); - test('split multiple targets with classical register', () => { - const targets: Register[] = [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 2 }, - { type: RegisterType.Qubit, qId: 1 }, - ]; - let targetsY: number[][] = [ - [startY], - [startY + registerHeight, startY + registerHeight * 2 + classicalRegHeight], - ]; - expect(_splitTargetsY(targets, [startY + classicalRegHeight], registers)).toEqual(targetsY); - expect(_splitTargetsY(targets, [10, startY + classicalRegHeight], registers)).toEqual(targetsY); - expect(_splitTargetsY(targets, [60, startY + classicalRegHeight], registers)).toEqual(targetsY); + { + type: RegisterType.Classical, + y: startY + registerHeight * 2 + classicalRegHeight * 4, + }, + ], + }, + }; + test("adjacent qubit regs", () => { + const targets: Register[] = [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 2 }, + { type: RegisterType.Qubit, qId: 1 }, + ]; + const targetsY: number[] = [ + startY, + startY + registerHeight, + startY + registerHeight * 2 + classicalRegHeight, + ]; + expect(_splitTargetsY(targets, [], registers)).toEqual([targetsY]); + expect(_splitTargetsY(targets, [0], registers)).toEqual([targetsY]); + expect( + _splitTargetsY(targets, [startY + registerHeight * 3], registers), + ).toEqual([targetsY]); + expect( + _splitTargetsY(targets, [0, startY + registerHeight * 3], registers), + ).toEqual([targetsY]); + }); + test("adjacent classical regs", () => { + const targets: Register[] = [ + { type: RegisterType.Classical, qId: 2, cId: 0 }, + { type: RegisterType.Classical, qId: 2, cId: 2 }, + { type: RegisterType.Classical, qId: 2, cId: 1 }, + ]; + const targetsY: number[] = [ + startY + registerHeight * 2 + classicalRegHeight * 2, + startY + registerHeight * 2 + classicalRegHeight * 3, + startY + registerHeight * 2 + classicalRegHeight * 4, + ]; + expect(_splitTargetsY(targets, [], registers)).toEqual([targetsY]); + expect(_splitTargetsY(targets, [0], registers)).toEqual([targetsY]); + expect( + _splitTargetsY( + targets, + [startY + registerHeight * 3 + classicalRegHeight * 4], + registers, + ), + ).toEqual([targetsY]); + expect( + _splitTargetsY( + targets, + [0, startY + registerHeight * 3 + classicalRegHeight * 4], + registers, + ), + ).toEqual([targetsY]); + }); + test("adjacent qubit/classical regs", () => { + const targets: Register[] = [ + { type: RegisterType.Qubit, qId: 2 }, + { type: RegisterType.Classical, qId: 1, cId: 0 }, + { type: RegisterType.Classical, qId: 2, cId: 0 }, + ]; + const targetsY: number[] = [ + startY + registerHeight + classicalRegHeight, + startY + registerHeight * 2 + classicalRegHeight, + startY + registerHeight * 2 + classicalRegHeight * 2, + ]; + expect(_splitTargetsY(targets, [], registers)).toEqual([targetsY]); + expect(_splitTargetsY(targets, [0], registers)).toEqual([targetsY]); + expect( + _splitTargetsY( + targets, + [startY + registerHeight * 3 + classicalRegHeight * 4], + registers, + ), + ).toEqual([targetsY]); + expect( + _splitTargetsY( + targets, + [0, startY + registerHeight * 3 + classicalRegHeight * 4], + registers, + ), + ).toEqual([targetsY]); + }); + test("single target", () => { + const targets: Register[] = [{ type: RegisterType.Qubit, qId: 0 }]; + expect(_splitTargetsY(targets, [], registers)).toEqual([[startY]]); + expect(_splitTargetsY(targets, [0], registers)).toEqual([[startY]]); + expect( + _splitTargetsY(targets, [startY + registerHeight], registers), + ).toEqual([[startY]]); + expect( + _splitTargetsY(targets, [0, startY + registerHeight], registers), + ).toEqual([[startY]]); + }); + test("split non-adjacent qubit regs", () => { + const targets: Register[] = [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 2 }, + ]; + const targetsY: number[][] = [ + [startY], + [startY + registerHeight * 2 + classicalRegHeight], + ]; + expect(_splitTargetsY(targets, [], registers)).toEqual(targetsY); + expect(_splitTargetsY(targets, [0], registers)).toEqual(targetsY); + expect( + _splitTargetsY(targets, [startY + registerHeight * 3], registers), + ).toEqual(targetsY); + expect( + _splitTargetsY(targets, [0, startY + registerHeight * 3], registers), + ).toEqual(targetsY); + }); + test("split two qubit regs with classical register", () => { + const targets: Register[] = [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + ]; + const targetsY: number[][] = [[startY], [startY + registerHeight]]; + expect( + _splitTargetsY(targets, [startY + classicalRegHeight], registers), + ).toEqual(targetsY); + expect( + _splitTargetsY(targets, [0, startY + classicalRegHeight], registers), + ).toEqual(targetsY); + expect( + _splitTargetsY( + targets, + [startY + registerHeight * 2, startY + classicalRegHeight], + registers, + ), + ).toEqual(targetsY); + expect( + _splitTargetsY( + targets, + [startY + registerHeight * 2, 0, startY + classicalRegHeight], + registers, + ), + ).toEqual(targetsY); + }); + test("split two classical regs with classical reg", () => { + const targets: Register[] = [ + { type: RegisterType.Classical, qId: 2, cId: 0 }, + { type: RegisterType.Classical, qId: 2, cId: 2 }, + ]; + const targetsY: number[][] = [ + [startY + registerHeight * 2 + classicalRegHeight * 2], + [startY + registerHeight * 2 + classicalRegHeight * 4], + ]; + expect( + _splitTargetsY( + targets, + [startY + registerHeight * 2 + classicalRegHeight * 3], + registers, + ), + ).toEqual(targetsY); + expect( + _splitTargetsY( + targets, + [0, startY + registerHeight * 2 + classicalRegHeight * 3], + registers, + ), + ).toEqual(targetsY); + expect( + _splitTargetsY( + targets, + [ + startY + registerHeight * 3 + classicalRegHeight * 2, + startY + registerHeight * 2 + classicalRegHeight * 3, + ], + registers, + ), + ).toEqual(targetsY); + expect( + _splitTargetsY( + targets, + [ + startY + registerHeight * 3 + classicalRegHeight * 2, + 0, + startY + registerHeight * 2 + classicalRegHeight * 3, + ], + registers, + ), + ).toEqual(targetsY); + }); + test("split multiple targets with classical register", () => { + const targets: Register[] = [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 2 }, + { type: RegisterType.Qubit, qId: 1 }, + ]; + let targetsY: number[][] = [ + [startY], + [ + startY + registerHeight, + startY + registerHeight * 2 + classicalRegHeight, + ], + ]; + expect( + _splitTargetsY(targets, [startY + classicalRegHeight], registers), + ).toEqual(targetsY); + expect( + _splitTargetsY(targets, [10, startY + classicalRegHeight], registers), + ).toEqual(targetsY); + expect( + _splitTargetsY(targets, [60, startY + classicalRegHeight], registers), + ).toEqual(targetsY); - targetsY = [[startY, startY + registerHeight], [startY + registerHeight * 2 + classicalRegHeight]]; - expect(_splitTargetsY(targets, [startY + registerHeight + classicalRegHeight], registers)).toEqual(targetsY); - }); + targetsY = [ + [startY, startY + registerHeight], + [startY + registerHeight * 2 + classicalRegHeight], + ]; + expect( + _splitTargetsY( + targets, + [startY + registerHeight + classicalRegHeight], + registers, + ), + ).toEqual(targetsY); + }); }); -describe('Testing _offsetChildrenX', () => { - const offset = 50; - test('no grandchildren', () => { - const children: Metadata[][] = [ - [ - { - type: GateType.X, - x: 0, - controlsY: [], - targetsY: [], - width: minGateWidth, - label: 'X', - }, - ], - ]; - const expected: Metadata[][] = [ - [ - { - type: GateType.X, - x: 50, - controlsY: [], - targetsY: [], - width: minGateWidth, - label: 'X', - }, - ], - ]; - _offsetChildrenX(children, offset); - expect(children).toEqual(expected); - }); - test('has grandchildren', () => { - const children: Metadata[][] = [ +describe("Testing _offsetChildrenX", () => { + const offset = 50; + test("no grandchildren", () => { + const children: Metadata[][] = [ + [ + { + type: GateType.X, + x: 0, + controlsY: [], + targetsY: [], + width: minGateWidth, + label: "X", + }, + ], + ]; + const expected: Metadata[][] = [ + [ + { + type: GateType.X, + x: 50, + controlsY: [], + targetsY: [], + width: minGateWidth, + label: "X", + }, + ], + ]; + _offsetChildrenX(children, offset); + expect(children).toEqual(expected); + }); + test("has grandchildren", () => { + const children: Metadata[][] = [ + [ + { + type: GateType.X, + x: 0, + controlsY: [], + targetsY: [], + width: minGateWidth, + label: "X", + children: [ [ - { - type: GateType.X, - x: 0, - controlsY: [], - targetsY: [], - width: minGateWidth, - label: 'X', - children: [ - [ - { - type: GateType.X, - x: 0, - controlsY: [], - targetsY: [], - width: minGateWidth, - label: 'X', - }, - ], - [], - ], - }, + { + type: GateType.X, + x: 0, + controlsY: [], + targetsY: [], + width: minGateWidth, + label: "X", + }, ], - ]; - const expected: Metadata[][] = [ + [], + ], + }, + ], + ]; + const expected: Metadata[][] = [ + [ + { + type: GateType.X, + x: 50, + controlsY: [], + targetsY: [], + width: minGateWidth, + label: "X", + children: [ [ - { - type: GateType.X, - x: 50, - controlsY: [], - targetsY: [], - width: minGateWidth, - label: 'X', - children: [ - [ - { - type: GateType.X, - x: 50, - controlsY: [], - targetsY: [], - width: minGateWidth, - label: 'X', - }, - ], - [], - ], - }, + { + type: GateType.X, + x: 50, + controlsY: [], + targetsY: [], + width: minGateWidth, + label: "X", + }, ], - ]; - _offsetChildrenX(children, offset); - expect(children).toEqual(expected); - }); - test('undefined child', () => { - expect(() => _offsetChildrenX(undefined, offset)).not.toThrow(); - }); + [], + ], + }, + ], + ]; + _offsetChildrenX(children, offset); + expect(children).toEqual(expected); + }); + test("undefined child", () => { + expect(() => _offsetChildrenX(undefined, offset)).not.toThrow(); + }); }); -describe('Testing _fillMetadataX', () => { - test('Non-classically-isControlled gate', () => { - const columnWidths: number[] = Array(1).fill(minGateWidth); - const expectedEndX = startX + minGateWidth + gatePadding * 2; - const opsMetadata: Metadata[][] = [ - [ - { - type: GateType.X, - x: 0, - controlsY: [], - targetsY: [], - label: 'X', - width: minGateWidth, - }, - ], - ]; - const expected: Metadata[][] = [ - [ - { - type: GateType.X, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [], - label: 'X', - width: minGateWidth, - }, - ], - ]; - const endX: number = _fillMetadataX(opsMetadata, columnWidths); - expect(opsMetadata).toEqual(expected); - expect(endX).toEqual(expectedEndX); - }); - test('classically-isControlled gate with no children', () => { - const columnWidths: number[] = Array(1).fill(minGateWidth); - const expectedEndX = startX + minGateWidth + gatePadding * 2; - const opsMetadata: Metadata[][] = [ +describe("Testing _fillMetadataX", () => { + test("Non-classically-isControlled gate", () => { + const columnWidths: number[] = Array(1).fill(minGateWidth); + const expectedEndX = startX + minGateWidth + gatePadding * 2; + const opsMetadata: Metadata[][] = [ + [ + { + type: GateType.X, + x: 0, + controlsY: [], + targetsY: [], + label: "X", + width: minGateWidth, + }, + ], + ]; + const expected: Metadata[][] = [ + [ + { + type: GateType.X, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [], + label: "X", + width: minGateWidth, + }, + ], + ]; + const endX: number = _fillMetadataX(opsMetadata, columnWidths); + expect(opsMetadata).toEqual(expected); + expect(endX).toEqual(expectedEndX); + }); + test("classically-isControlled gate with no children", () => { + const columnWidths: number[] = Array(1).fill(minGateWidth); + const expectedEndX = startX + minGateWidth + gatePadding * 2; + const opsMetadata: Metadata[][] = [ + [ + { + type: GateType.ClassicalControlled, + x: 0, + controlsY: [], + targetsY: [], + label: "X", + width: minGateWidth, + }, + ], + ]; + const expected: Metadata[][] = [ + [ + { + type: GateType.ClassicalControlled, + x: startX, + controlsY: [], + targetsY: [], + label: "X", + width: minGateWidth, + }, + ], + ]; + const endX: number = _fillMetadataX(opsMetadata, columnWidths); + expect(opsMetadata).toEqual(expected); + expect(endX).toEqual(expectedEndX); + }); + test("depth-1 children", () => { + const columnWidths: number[] = Array(1).fill( + minGateWidth + gatePadding * 2, + ); + const expectedEndX = startX + minGateWidth + gatePadding * 4; + const opsMetadata: Metadata[][] = [ + [ + { + type: GateType.ClassicalControlled, + x: 0, + controlsY: [], + targetsY: [], + children: [ [ - { - type: GateType.ClassicalControlled, - x: 0, - controlsY: [], - targetsY: [], - label: 'X', - width: minGateWidth, - }, + { + type: GateType.X, + x: 0, + controlsY: [], + targetsY: [], + label: "X", + width: minGateWidth, + }, ], - ]; - const expected: Metadata[][] = [ [ - { - type: GateType.ClassicalControlled, - x: startX, - controlsY: [], - targetsY: [], - label: 'X', - width: minGateWidth, - }, + { + type: GateType.X, + x: 0, + controlsY: [], + targetsY: [], + label: "X", + width: minGateWidth, + }, ], - ]; - const endX: number = _fillMetadataX(opsMetadata, columnWidths); - expect(opsMetadata).toEqual(expected); - expect(endX).toEqual(expectedEndX); - }); - test('depth-1 children', () => { - const columnWidths: number[] = Array(1).fill(minGateWidth + gatePadding * 2); - const expectedEndX = startX + minGateWidth + gatePadding * 4; - const opsMetadata: Metadata[][] = [ + ], + label: "X", + width: minGateWidth + controlBtnOffset + groupBoxPadding * 2, + }, + ], + ]; + const expected: Metadata[][] = [ + [ + { + type: GateType.ClassicalControlled, + x: startX, + controlsY: [], + targetsY: [], + children: [ [ - { - type: GateType.ClassicalControlled, - x: 0, - controlsY: [], - targetsY: [], - children: [ - [ - { - type: GateType.X, - x: 0, - controlsY: [], - targetsY: [], - label: 'X', - width: minGateWidth, - }, - ], - [ - { - type: GateType.X, - x: 0, - controlsY: [], - targetsY: [], - label: 'X', - width: minGateWidth, - }, - ], - ], - label: 'X', - width: minGateWidth + controlBtnOffset + groupBoxPadding * 2, - }, + { + type: GateType.X, + x: controlBtnOffset + groupBoxPadding, + controlsY: [], + targetsY: [], + label: "X", + width: minGateWidth, + }, ], - ]; - const expected: Metadata[][] = [ [ - { - type: GateType.ClassicalControlled, - x: startX, - controlsY: [], - targetsY: [], - children: [ - [ - { - type: GateType.X, - x: controlBtnOffset + groupBoxPadding, - controlsY: [], - targetsY: [], - label: 'X', - width: minGateWidth, - }, - ], - [ - { - type: GateType.X, - x: controlBtnOffset + groupBoxPadding, - controlsY: [], - targetsY: [], - label: 'X', - width: minGateWidth, - }, - ], - ], - label: 'X', - width: minGateWidth + controlBtnOffset + groupBoxPadding * 2, - }, + { + type: GateType.X, + x: controlBtnOffset + groupBoxPadding, + controlsY: [], + targetsY: [], + label: "X", + width: minGateWidth, + }, ], - ]; + ], + label: "X", + width: minGateWidth + controlBtnOffset + groupBoxPadding * 2, + }, + ], + ]; - const endX: number = _fillMetadataX(opsMetadata, columnWidths); - expect(opsMetadata).toEqual(expected); - expect(endX).toEqual(expectedEndX); - }); - test('empty args', () => { - const opsMetadata: Metadata[][] = []; - const endX: number = _fillMetadataX(opsMetadata, []); - expect(opsMetadata).toEqual([]); - expect(endX).toEqual(startX); - }); + const endX: number = _fillMetadataX(opsMetadata, columnWidths); + expect(opsMetadata).toEqual(expected); + expect(endX).toEqual(expectedEndX); + }); + test("empty args", () => { + const opsMetadata: Metadata[][] = []; + const endX: number = _fillMetadataX(opsMetadata, []); + expect(opsMetadata).toEqual([]); + expect(endX).toEqual(startX); + }); }); -describe('Testing processOperations', () => { - test('single qubit gates', () => { - const rxWidth = 52; - const operations: Operation[] = [ - { - gate: 'H', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ qId: 0 }], - }, - { - gate: 'H', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ qId: 0 }], - }, - { - gate: 'H', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ qId: 1 }], - }, - { - gate: 'RX', - displayArgs: '(0.25)', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ qId: 1 }], - }, - ]; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - }; - const expectedOps: Metadata[] = [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [[startY]], - label: 'H', - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + (minGateWidth + gatePadding * 2) + rxWidth / 2, - controlsY: [], - targetsY: [[startY]], - label: 'H', - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [[startY + registerHeight]], - label: 'H', - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + (minGateWidth + gatePadding * 2) + rxWidth / 2, - controlsY: [], - targetsY: [[startY + registerHeight]], - label: 'RX', - displayArgs: '(0.25)', - width: rxWidth, - }, - ]; - const expectedWidth: number = startX + minGateWidth + rxWidth + gatePadding * 4; - const { metadataList, svgWidth } = processOperations(operations, registers); - expect(metadataList).toEqual(expectedOps); - expect(svgWidth).toEqual(expectedWidth); - }); - test('single wide qubit gates', () => { - const expectedCustomWidth = 67; - const operations: Operation[] = [ - { - gate: 'H', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'FooBar', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'H', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - ]; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - }; - const expectedOps: Metadata[] = [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [[startY]], - label: 'H', - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + (minGateWidth + gatePadding * 2) + expectedCustomWidth / 2, - controlsY: [], - targetsY: [[startY]], - label: 'FooBar', - width: expectedCustomWidth, - }, - { - type: GateType.Unitary, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [[startY + registerHeight]], - label: 'H', - width: minGateWidth, - }, - ]; - const expectedWidth: number = startX + minGateWidth + expectedCustomWidth + gatePadding * 4; - const { metadataList, svgWidth } = processOperations(operations, registers); - expect(metadataList).toEqual(expectedOps); - expect(svgWidth).toEqual(expectedWidth); - }); - test('single and multi qubit gates', () => { - const operations: Operation[] = [ - { - gate: 'H', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'H', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - ]; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - }; - const expectedOps: Metadata[] = [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [[startY]], - label: 'H', - width: minGateWidth, - }, - { - type: GateType.Cnot, - x: startX + (minGateWidth + gatePadding * 2) + minGateWidth / 2, - controlsY: [startY + registerHeight], - targetsY: [startY], - label: 'X', - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + (minGateWidth + gatePadding * 2) * 2 + minGateWidth / 2, - controlsY: [], - targetsY: [[startY + registerHeight]], - label: 'H', - width: minGateWidth, - }, - ]; - const expectedWidth: number = startX + (minGateWidth + gatePadding * 2) * 3; - const { metadataList, svgWidth } = processOperations(operations, registers); - expect(metadataList).toEqual(expectedOps); - expect(svgWidth).toEqual(expectedWidth); - }); - test('classically-controlled gates', () => { - const op: Operation = { - gate: 'X', - isMeasurement: false, - isConditional: true, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - ], - children: [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - conditionalRender: ConditionalRender.OnZero, - }, - { - gate: 'H', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - conditionalRender: ConditionalRender.OnOne, - }, - { - gate: 'Z', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - conditionalRender: ConditionalRender.OnZero, - }, - ], - }; - const registers: RegisterMap = { - 0: { - type: RegisterType.Qubit, - y: startY, - children: [{ type: RegisterType.Classical, y: startY + classicalRegHeight }], - }, - 1: { type: RegisterType.Qubit, y: startY + classicalRegHeight * 2 }, - }; - const metadata: Metadata = { - type: GateType.ClassicalControlled, - x: startX, - controlsY: [startY + classicalRegHeight], - targetsY: [startY, startY + classicalRegHeight * 2], - label: '', - width: minGateWidth * 2 + gatePadding * 2 + controlBtnOffset + groupBoxPadding * 2, - children: [ - [ - { - type: GateType.X, - x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, - controlsY: [], - targetsY: [startY], - label: 'X', - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: - startX + - minGateWidth + - minGateWidth / 2 + - gatePadding * 2 + - controlBtnOffset + - groupBoxPadding, - controlsY: [], - targetsY: [[startY]], - label: 'Z', - width: minGateWidth, - }, - ], - [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, - controlsY: [], - targetsY: [[startY + classicalRegHeight * 2]], - label: 'H', - width: minGateWidth, - }, - ], - ], - }; - const expectedWidth: number = - startX + minGateWidth * 2 + gatePadding * 4 + controlBtnOffset + groupBoxPadding * 2; - const { metadataList, svgWidth } = processOperations([op], registers); - expect(metadataList).toEqual([metadata]); - expect(svgWidth).toEqual(expectedWidth); - }); - test('grouped gates', () => { - const op: Operation = { - gate: 'Foo', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - ], - conditionalRender: ConditionalRender.AsGroup, - children: [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'H', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: 'Z', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ], - }; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - }; - const metadata: Metadata = { - type: GateType.Group, - x: startX, +describe("Testing processOperations", () => { + test("single qubit gates", () => { + const rxWidth = 52; + const operations: Operation[] = [ + { + gate: "H", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ qId: 0 }], + }, + { + gate: "H", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ qId: 0 }], + }, + { + gate: "H", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ qId: 1 }], + }, + { + gate: "RX", + displayArgs: "(0.25)", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ qId: 1 }], + }, + ]; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + }; + const expectedOps: Metadata[] = [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [[startY]], + label: "H", + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + (minGateWidth + gatePadding * 2) + rxWidth / 2, + controlsY: [], + targetsY: [[startY]], + label: "H", + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [[startY + registerHeight]], + label: "H", + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + (minGateWidth + gatePadding * 2) + rxWidth / 2, + controlsY: [], + targetsY: [[startY + registerHeight]], + label: "RX", + displayArgs: "(0.25)", + width: rxWidth, + }, + ]; + const expectedWidth: number = + startX + minGateWidth + rxWidth + gatePadding * 4; + const { metadataList, svgWidth } = processOperations(operations, registers); + expect(metadataList).toEqual(expectedOps); + expect(svgWidth).toEqual(expectedWidth); + }); + test("single wide qubit gates", () => { + const expectedCustomWidth = 67; + const operations: Operation[] = [ + { + gate: "H", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "FooBar", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "H", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + ]; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + }; + const expectedOps: Metadata[] = [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [[startY]], + label: "H", + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + (minGateWidth + gatePadding * 2) + expectedCustomWidth / 2, + controlsY: [], + targetsY: [[startY]], + label: "FooBar", + width: expectedCustomWidth, + }, + { + type: GateType.Unitary, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [[startY + registerHeight]], + label: "H", + width: minGateWidth, + }, + ]; + const expectedWidth: number = + startX + minGateWidth + expectedCustomWidth + gatePadding * 4; + const { metadataList, svgWidth } = processOperations(operations, registers); + expect(metadataList).toEqual(expectedOps); + expect(svgWidth).toEqual(expectedWidth); + }); + test("single and multi qubit gates", () => { + const operations: Operation[] = [ + { + gate: "H", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 1 }], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "H", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + ]; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + }; + const expectedOps: Metadata[] = [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [[startY]], + label: "H", + width: minGateWidth, + }, + { + type: GateType.Cnot, + x: startX + (minGateWidth + gatePadding * 2) + minGateWidth / 2, + controlsY: [startY + registerHeight], + targetsY: [startY], + label: "X", + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + (minGateWidth + gatePadding * 2) * 2 + minGateWidth / 2, + controlsY: [], + targetsY: [[startY + registerHeight]], + label: "H", + width: minGateWidth, + }, + ]; + const expectedWidth: number = startX + (minGateWidth + gatePadding * 2) * 3; + const { metadataList, svgWidth } = processOperations(operations, registers); + expect(metadataList).toEqual(expectedOps); + expect(svgWidth).toEqual(expectedWidth); + }); + test("classically-controlled gates", () => { + const op: Operation = { + gate: "X", + isMeasurement: false, + isConditional: true, + isControlled: true, + isAdjoint: false, + controls: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + ], + children: [ + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + conditionalRender: ConditionalRender.OnZero, + }, + { + gate: "H", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + conditionalRender: ConditionalRender.OnOne, + }, + { + gate: "Z", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + conditionalRender: ConditionalRender.OnZero, + }, + ], + }; + const registers: RegisterMap = { + 0: { + type: RegisterType.Qubit, + y: startY, + children: [ + { type: RegisterType.Classical, y: startY + classicalRegHeight }, + ], + }, + 1: { type: RegisterType.Qubit, y: startY + classicalRegHeight * 2 }, + }; + const metadata: Metadata = { + type: GateType.ClassicalControlled, + x: startX, + controlsY: [startY + classicalRegHeight], + targetsY: [startY, startY + classicalRegHeight * 2], + label: "", + width: + minGateWidth * 2 + + gatePadding * 2 + + controlBtnOffset + + groupBoxPadding * 2, + children: [ + [ + { + type: GateType.X, + x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, controlsY: [], - targetsY: [startY, startY + registerHeight], - label: '', - width: minGateWidth * 2 + gatePadding * 2 + groupBoxPadding * 2, - dataAttributes: { expanded: 'true' }, - children: [ - { - type: GateType.X, - x: startX + minGateWidth / 2 + groupBoxPadding, - controlsY: [], - targetsY: [startY], - label: 'X', - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + minGateWidth + minGateWidth / 2 + gatePadding * 2 + groupBoxPadding, - controlsY: [], - targetsY: [[startY]], - label: 'Z', - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + minGateWidth / 2 + groupBoxPadding, - controlsY: [], - targetsY: [[startY + registerHeight]], - label: 'H', - width: minGateWidth, - }, - ], - }; - const expectedWidth: number = startX + minGateWidth * 2 + gatePadding * 4 + groupBoxPadding * 2; - const { metadataList, svgWidth } = processOperations([op], registers); - expect(metadataList).toEqual([metadata]); - expect(svgWidth).toEqual(expectedWidth); - }); - test('nested grouped gates', () => { - const op: Operation = { - gate: 'Foo', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - ], - conditionalRender: ConditionalRender.AsGroup, - children: [ - { - gate: 'Foo', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - conditionalRender: ConditionalRender.AsGroup, - children: [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Z', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ], - }, - { - gate: 'H', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - ], - }; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - }; - const metadata: Metadata = { - type: GateType.Group, - x: startX, + targetsY: [startY], + label: "X", + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: + startX + + minGateWidth + + minGateWidth / 2 + + gatePadding * 2 + + controlBtnOffset + + groupBoxPadding, controlsY: [], - targetsY: [startY, startY + registerHeight], - label: '', - width: minGateWidth * 2 + gatePadding * 2 + groupBoxPadding * 4, - dataAttributes: { expanded: 'true' }, - children: [ - { - type: GateType.Group, - x: startX + gatePadding, - controlsY: [], - targetsY: [startY], - label: '', - width: minGateWidth * 2 + gatePadding * 2 + groupBoxPadding * 2, - dataAttributes: { expanded: 'true' }, - children: [ - { - type: GateType.X, - x: startX + minGateWidth / 2 + groupBoxPadding * 2, - controlsY: [], - targetsY: [startY], - label: 'X', - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + minGateWidth + minGateWidth / 2 + gatePadding * 2 + groupBoxPadding * 2, - controlsY: [], - targetsY: [[startY]], - label: 'Z', - width: minGateWidth, - }, - ], - }, - { - type: GateType.Unitary, - x: startX + minGateWidth + gatePadding + groupBoxPadding * 2, // startX + half of above gate's width + padding - controlsY: [], - targetsY: [[startY + registerHeight]], - label: 'H', - width: minGateWidth, - }, - ], - }; - const expectedWidth: number = startX + minGateWidth * 2 + gatePadding * 4 + groupBoxPadding * 4; - const { metadataList, svgWidth } = processOperations([op], registers); - expect(metadataList).toEqual([metadata]); - expect(svgWidth).toEqual(expectedWidth); - }); - test('measure gates', () => { - const operations: Operation[] = [ - { - gate: 'H', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'M', - isMeasurement: true, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], - }, - { - gate: 'H', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: 'M', - isMeasurement: true, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [{ type: RegisterType.Classical, qId: 0, cId: 1 }], - }, - ]; - const registers: RegisterMap = { - 0: { - type: RegisterType.Qubit, - y: startY, - children: [ - { type: RegisterType.Classical, y: startY + classicalRegHeight }, - { type: RegisterType.Classical, y: startY + classicalRegHeight * 2 }, - ], - }, - 1: { type: RegisterType.Qubit, y: startY + classicalRegHeight * 3 }, - }; - const expectedOps: Metadata[] = [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [[startY]], - label: 'H', - width: minGateWidth, - }, - { - type: GateType.Measure, - x: startX + minGateWidth + gatePadding * 2 + minGateWidth / 2, - controlsY: [startY], - targetsY: [startY + classicalRegHeight], - label: '', - width: minGateWidth, - }, - { - type: GateType.Measure, - x: startX + (minGateWidth + gatePadding * 2) * 2 + minGateWidth / 2, - controlsY: [startY], - targetsY: [startY + classicalRegHeight * 2], - label: '', - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [[startY + classicalRegHeight * 3]], - label: 'H', - width: minGateWidth, - }, - ]; - const expectedWidth: number = startX + (minGateWidth + gatePadding * 2) * 3; - const { metadataList, svgWidth } = processOperations(operations, registers); - expect(metadataList).toEqual(expectedOps); - expect(svgWidth).toEqual(expectedWidth); - }); - test('skipped registers', () => { - const operations: Operation[] = [ - { - gate: 'H', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'H', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 2 }], - }, - ]; - const registers: RegisterMap = { - 0: { - type: RegisterType.Qubit, - y: startY, - children: [ - { type: RegisterType.Classical, y: startY + classicalRegHeight }, - { type: RegisterType.Classical, y: startY + classicalRegHeight * 2 }, - ], - }, - 2: { type: RegisterType.Qubit, y: startY + classicalRegHeight * 3 }, - }; - const expectedOps: Metadata[] = [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [[startY]], - label: 'H', - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [[startY + classicalRegHeight * 3]], - label: 'H', - width: minGateWidth, - }, - ]; - const expectedWidth: number = startX + minGateWidth + gatePadding * 2; - const { metadataList, svgWidth } = processOperations(operations, registers); - expect(metadataList).toEqual(expectedOps); - expect(svgWidth).toEqual(expectedWidth); - }); - test('no operations', () => { - const operations: Operation[] = []; - const registers: RegisterMap = {}; - const { metadataList, svgWidth } = processOperations(operations, registers); - expect(metadataList).toEqual([]); - expect(svgWidth).toEqual(startX); - }); + targetsY: [[startY]], + label: "Z", + width: minGateWidth, + }, + ], + [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, + controlsY: [], + targetsY: [[startY + classicalRegHeight * 2]], + label: "H", + width: minGateWidth, + }, + ], + ], + }; + const expectedWidth: number = + startX + + minGateWidth * 2 + + gatePadding * 4 + + controlBtnOffset + + groupBoxPadding * 2; + const { metadataList, svgWidth } = processOperations([op], registers); + expect(metadataList).toEqual([metadata]); + expect(svgWidth).toEqual(expectedWidth); + }); + test("grouped gates", () => { + const op: Operation = { + gate: "Foo", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + ], + conditionalRender: ConditionalRender.AsGroup, + children: [ + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "H", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: "Z", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ], + }; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + }; + const metadata: Metadata = { + type: GateType.Group, + x: startX, + controlsY: [], + targetsY: [startY, startY + registerHeight], + label: "", + width: minGateWidth * 2 + gatePadding * 2 + groupBoxPadding * 2, + dataAttributes: { expanded: "true" }, + children: [ + { + type: GateType.X, + x: startX + minGateWidth / 2 + groupBoxPadding, + controlsY: [], + targetsY: [startY], + label: "X", + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: + startX + + minGateWidth + + minGateWidth / 2 + + gatePadding * 2 + + groupBoxPadding, + controlsY: [], + targetsY: [[startY]], + label: "Z", + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + minGateWidth / 2 + groupBoxPadding, + controlsY: [], + targetsY: [[startY + registerHeight]], + label: "H", + width: minGateWidth, + }, + ], + }; + const expectedWidth: number = + startX + minGateWidth * 2 + gatePadding * 4 + groupBoxPadding * 2; + const { metadataList, svgWidth } = processOperations([op], registers); + expect(metadataList).toEqual([metadata]); + expect(svgWidth).toEqual(expectedWidth); + }); + test("nested grouped gates", () => { + const op: Operation = { + gate: "Foo", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [ + { type: RegisterType.Qubit, qId: 0 }, + { type: RegisterType.Qubit, qId: 1 }, + ], + conditionalRender: ConditionalRender.AsGroup, + children: [ + { + gate: "Foo", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + conditionalRender: ConditionalRender.AsGroup, + children: [ + { + gate: "X", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "Z", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ], + }, + { + gate: "H", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + ], + }; + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + }; + const metadata: Metadata = { + type: GateType.Group, + x: startX, + controlsY: [], + targetsY: [startY, startY + registerHeight], + label: "", + width: minGateWidth * 2 + gatePadding * 2 + groupBoxPadding * 4, + dataAttributes: { expanded: "true" }, + children: [ + { + type: GateType.Group, + x: startX + gatePadding, + controlsY: [], + targetsY: [startY], + label: "", + width: minGateWidth * 2 + gatePadding * 2 + groupBoxPadding * 2, + dataAttributes: { expanded: "true" }, + children: [ + { + type: GateType.X, + x: startX + minGateWidth / 2 + groupBoxPadding * 2, + controlsY: [], + targetsY: [startY], + label: "X", + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: + startX + + minGateWidth + + minGateWidth / 2 + + gatePadding * 2 + + groupBoxPadding * 2, + controlsY: [], + targetsY: [[startY]], + label: "Z", + width: minGateWidth, + }, + ], + }, + { + type: GateType.Unitary, + x: startX + minGateWidth + gatePadding + groupBoxPadding * 2, // startX + half of above gate's width + padding + controlsY: [], + targetsY: [[startY + registerHeight]], + label: "H", + width: minGateWidth, + }, + ], + }; + const expectedWidth: number = + startX + minGateWidth * 2 + gatePadding * 4 + groupBoxPadding * 4; + const { metadataList, svgWidth } = processOperations([op], registers); + expect(metadataList).toEqual([metadata]); + expect(svgWidth).toEqual(expectedWidth); + }); + test("measure gates", () => { + const operations: Operation[] = [ + { + gate: "H", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "M", + isMeasurement: true, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], + }, + { + gate: "H", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 1 }], + }, + { + gate: "M", + isMeasurement: true, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [{ type: RegisterType.Qubit, qId: 0 }], + targets: [{ type: RegisterType.Classical, qId: 0, cId: 1 }], + }, + ]; + const registers: RegisterMap = { + 0: { + type: RegisterType.Qubit, + y: startY, + children: [ + { type: RegisterType.Classical, y: startY + classicalRegHeight }, + { type: RegisterType.Classical, y: startY + classicalRegHeight * 2 }, + ], + }, + 1: { type: RegisterType.Qubit, y: startY + classicalRegHeight * 3 }, + }; + const expectedOps: Metadata[] = [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [[startY]], + label: "H", + width: minGateWidth, + }, + { + type: GateType.Measure, + x: startX + minGateWidth + gatePadding * 2 + minGateWidth / 2, + controlsY: [startY], + targetsY: [startY + classicalRegHeight], + label: "", + width: minGateWidth, + }, + { + type: GateType.Measure, + x: startX + (minGateWidth + gatePadding * 2) * 2 + minGateWidth / 2, + controlsY: [startY], + targetsY: [startY + classicalRegHeight * 2], + label: "", + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [[startY + classicalRegHeight * 3]], + label: "H", + width: minGateWidth, + }, + ]; + const expectedWidth: number = startX + (minGateWidth + gatePadding * 2) * 3; + const { metadataList, svgWidth } = processOperations(operations, registers); + expect(metadataList).toEqual(expectedOps); + expect(svgWidth).toEqual(expectedWidth); + }); + test("skipped registers", () => { + const operations: Operation[] = [ + { + gate: "H", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: "H", + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 2 }], + }, + ]; + const registers: RegisterMap = { + 0: { + type: RegisterType.Qubit, + y: startY, + children: [ + { type: RegisterType.Classical, y: startY + classicalRegHeight }, + { type: RegisterType.Classical, y: startY + classicalRegHeight * 2 }, + ], + }, + 2: { type: RegisterType.Qubit, y: startY + classicalRegHeight * 3 }, + }; + const expectedOps: Metadata[] = [ + { + type: GateType.Unitary, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [[startY]], + label: "H", + width: minGateWidth, + }, + { + type: GateType.Unitary, + x: startX + minGateWidth / 2, + controlsY: [], + targetsY: [[startY + classicalRegHeight * 3]], + label: "H", + width: minGateWidth, + }, + ]; + const expectedWidth: number = startX + minGateWidth + gatePadding * 2; + const { metadataList, svgWidth } = processOperations(operations, registers); + expect(metadataList).toEqual(expectedOps); + expect(svgWidth).toEqual(expectedWidth); + }); + test("no operations", () => { + const operations: Operation[] = []; + const registers: RegisterMap = {}; + const { metadataList, svgWidth } = processOperations(operations, registers); + expect(metadataList).toEqual([]); + expect(svgWidth).toEqual(startX); + }); }); diff --git a/circuit_vis/__tests__/registerFormatter.test.ts b/circuit_vis/__tests__/registerFormatter.test.ts index 9723bead0a..1fec69e603 100644 --- a/circuit_vis/__tests__/registerFormatter.test.ts +++ b/circuit_vis/__tests__/registerFormatter.test.ts @@ -1,165 +1,205 @@ -import { formatRegisters, _classicalRegister, _qubitRegister } from '../src/formatters/registerFormatter'; -import { RegisterMap, RegisterType } from '../src/register'; -import { Metadata, GateType } from '../src/metadata'; -import { startY, registerHeight, classicalRegHeight, startX, minGateWidth } from '../src/constants'; +import { + formatRegisters, + _classicalRegister, + _qubitRegister, +} from "../src/formatters/registerFormatter"; +import { RegisterMap, RegisterType } from "../src/register"; +import { Metadata, GateType } from "../src/metadata"; +import { + startY, + registerHeight, + classicalRegHeight, + startX, + minGateWidth, +} from "../src/constants"; -describe('Testing _classicalRegister', () => { - test('register with normal width', () => { - expect(_classicalRegister(10, 10, 100, 20)).toMatchSnapshot(); - expect(_classicalRegister(10, 10, 100, 20)).toMatchSnapshot(); - expect(_classicalRegister(10, 10, 100, 20)).toMatchSnapshot(); - }); - test('register with small width', () => { - expect(_classicalRegister(10, 10, 5, 20)).toMatchSnapshot(); - expect(_classicalRegister(10, 10, 5, 20)).toMatchSnapshot(); - expect(_classicalRegister(10, 10, 5, 20)).toMatchSnapshot(); - }); - test('register with large width', () => { - expect(_classicalRegister(10, 10, 500, 20)).toMatchSnapshot(); - expect(_classicalRegister(10, 10, 500, 20)).toMatchSnapshot(); - expect(_classicalRegister(10, 10, 500, 20)).toMatchSnapshot(); - }); - test('register with label offset', () => { - expect(_classicalRegister(10, 10, 100, 20)).toMatchSnapshot(); - expect(_classicalRegister(10, 10, 100, 20)).toMatchSnapshot(); - expect(_classicalRegister(10, 10, 100, 20)).toMatchSnapshot(); - }); +describe("Testing _classicalRegister", () => { + test("register with normal width", () => { + expect(_classicalRegister(10, 10, 100, 20)).toMatchSnapshot(); + expect(_classicalRegister(10, 10, 100, 20)).toMatchSnapshot(); + expect(_classicalRegister(10, 10, 100, 20)).toMatchSnapshot(); + }); + test("register with small width", () => { + expect(_classicalRegister(10, 10, 5, 20)).toMatchSnapshot(); + expect(_classicalRegister(10, 10, 5, 20)).toMatchSnapshot(); + expect(_classicalRegister(10, 10, 5, 20)).toMatchSnapshot(); + }); + test("register with large width", () => { + expect(_classicalRegister(10, 10, 500, 20)).toMatchSnapshot(); + expect(_classicalRegister(10, 10, 500, 20)).toMatchSnapshot(); + expect(_classicalRegister(10, 10, 500, 20)).toMatchSnapshot(); + }); + test("register with label offset", () => { + expect(_classicalRegister(10, 10, 100, 20)).toMatchSnapshot(); + expect(_classicalRegister(10, 10, 100, 20)).toMatchSnapshot(); + expect(_classicalRegister(10, 10, 100, 20)).toMatchSnapshot(); + }); }); -describe('Testing _qubitRegister', () => { - test('register with normal width', () => { - expect(_qubitRegister(0, 100, 20)).toMatchSnapshot(); - expect(_qubitRegister(1, 100, 20)).toMatchSnapshot(); - expect(_qubitRegister(2, 100, 20)).toMatchSnapshot(); - }); - test('register with small width', () => { - expect(_qubitRegister(0, 5, 20)).toMatchSnapshot(); - expect(_qubitRegister(1, 5, 20)).toMatchSnapshot(); - expect(_qubitRegister(2, 5, 20)).toMatchSnapshot(); - }); - test('register with large width', () => { - expect(_qubitRegister(0, 500, 20)).toMatchSnapshot(); - expect(_qubitRegister(1, 500, 20)).toMatchSnapshot(); - expect(_qubitRegister(2, 500, 20)).toMatchSnapshot(); - }); - test('register with label offset', () => { - expect(_qubitRegister(0, 100, 20, 0)).toMatchSnapshot(); - expect(_qubitRegister(1, 100, 20, 5)).toMatchSnapshot(); - expect(_qubitRegister(2, 100, 20, 50)).toMatchSnapshot(); - }); +describe("Testing _qubitRegister", () => { + test("register with normal width", () => { + expect(_qubitRegister(0, 100, 20)).toMatchSnapshot(); + expect(_qubitRegister(1, 100, 20)).toMatchSnapshot(); + expect(_qubitRegister(2, 100, 20)).toMatchSnapshot(); + }); + test("register with small width", () => { + expect(_qubitRegister(0, 5, 20)).toMatchSnapshot(); + expect(_qubitRegister(1, 5, 20)).toMatchSnapshot(); + expect(_qubitRegister(2, 5, 20)).toMatchSnapshot(); + }); + test("register with large width", () => { + expect(_qubitRegister(0, 500, 20)).toMatchSnapshot(); + expect(_qubitRegister(1, 500, 20)).toMatchSnapshot(); + expect(_qubitRegister(2, 500, 20)).toMatchSnapshot(); + }); + test("register with label offset", () => { + expect(_qubitRegister(0, 100, 20, 0)).toMatchSnapshot(); + expect(_qubitRegister(1, 100, 20, 5)).toMatchSnapshot(); + expect(_qubitRegister(2, 100, 20, 50)).toMatchSnapshot(); + }); }); -describe('Testing formatRegisters', () => { - test('1 quantum register', () => { - const registers: RegisterMap = { 0: { type: RegisterType.Qubit, y: startY } }; - // Normal width - expect(formatRegisters(registers, [], startX + 100)).toMatchSnapshot(); - // Small width - expect(formatRegisters(registers, [], startX + 5)).toMatchSnapshot(); - // Large width - expect(formatRegisters(registers, [], startX + 500)).toMatchSnapshot(); - }); - test('Multiple quantum registers', () => { - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, - 3: { type: RegisterType.Qubit, y: startY + registerHeight * 3 }, - }; - // Normal width - expect(formatRegisters(registers, [], startX + 100)).toMatchSnapshot(); - // Small width - expect(formatRegisters(registers, [], startX + 5)).toMatchSnapshot(); - // Large width - expect(formatRegisters(registers, [], startX + 500)).toMatchSnapshot(); - }); - test('Skipped quantum registers', () => { - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, - 3: { type: RegisterType.Qubit, y: startY + registerHeight * 3 }, - }; - // Normal width - expect(formatRegisters(registers, [], startX + 100)).toMatchSnapshot(); - // Small width - expect(formatRegisters(registers, [], startX + 5)).toMatchSnapshot(); - // Large width - expect(formatRegisters(registers, [], startX + 500)).toMatchSnapshot(); - }); - test('Quantum and classical registers', () => { - let registers: RegisterMap = { - 0: { - type: RegisterType.Qubit, - y: startY, - children: [{ type: RegisterType.Classical, y: startY + classicalRegHeight }], - }, - 1: { type: RegisterType.Qubit, y: startY + classicalRegHeight * 2 }, - 2: { type: RegisterType.Qubit, y: startY + registerHeight + classicalRegHeight * 2 }, - }; - let measureGates: Metadata[] = [ - { - type: GateType.Measure, - x: startX, - controlsY: [startY], - targetsY: [startY + classicalRegHeight], - label: '', - width: minGateWidth, - }, - ]; - // Normal width - expect(formatRegisters(registers, measureGates, startX + 100)).toMatchSnapshot(); - // Small width - expect(formatRegisters(registers, measureGates, startX + 5)).toMatchSnapshot(); - // Large width - expect(formatRegisters(registers, measureGates, startX + 500)).toMatchSnapshot(); +describe("Testing formatRegisters", () => { + test("1 quantum register", () => { + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + }; + // Normal width + expect(formatRegisters(registers, [], startX + 100)).toMatchSnapshot(); + // Small width + expect(formatRegisters(registers, [], startX + 5)).toMatchSnapshot(); + // Large width + expect(formatRegisters(registers, [], startX + 500)).toMatchSnapshot(); + }); + test("Multiple quantum registers", () => { + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { type: RegisterType.Qubit, y: startY + registerHeight }, + 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, + 3: { type: RegisterType.Qubit, y: startY + registerHeight * 3 }, + }; + // Normal width + expect(formatRegisters(registers, [], startX + 100)).toMatchSnapshot(); + // Small width + expect(formatRegisters(registers, [], startX + 5)).toMatchSnapshot(); + // Large width + expect(formatRegisters(registers, [], startX + 500)).toMatchSnapshot(); + }); + test("Skipped quantum registers", () => { + const registers: RegisterMap = { + 0: { type: RegisterType.Qubit, y: startY }, + 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, + 3: { type: RegisterType.Qubit, y: startY + registerHeight * 3 }, + }; + // Normal width + expect(formatRegisters(registers, [], startX + 100)).toMatchSnapshot(); + // Small width + expect(formatRegisters(registers, [], startX + 5)).toMatchSnapshot(); + // Large width + expect(formatRegisters(registers, [], startX + 500)).toMatchSnapshot(); + }); + test("Quantum and classical registers", () => { + let registers: RegisterMap = { + 0: { + type: RegisterType.Qubit, + y: startY, + children: [ + { type: RegisterType.Classical, y: startY + classicalRegHeight }, + ], + }, + 1: { type: RegisterType.Qubit, y: startY + classicalRegHeight * 2 }, + 2: { + type: RegisterType.Qubit, + y: startY + registerHeight + classicalRegHeight * 2, + }, + }; + let measureGates: Metadata[] = [ + { + type: GateType.Measure, + x: startX, + controlsY: [startY], + targetsY: [startY + classicalRegHeight], + label: "", + width: minGateWidth, + }, + ]; + // Normal width + expect( + formatRegisters(registers, measureGates, startX + 100), + ).toMatchSnapshot(); + // Small width + expect( + formatRegisters(registers, measureGates, startX + 5), + ).toMatchSnapshot(); + // Large width + expect( + formatRegisters(registers, measureGates, startX + 500), + ).toMatchSnapshot(); - registers = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { - type: RegisterType.Qubit, - y: startY + registerHeight, - children: [ - { type: RegisterType.Classical, y: startY + registerHeight + classicalRegHeight }, - { type: RegisterType.Classical, y: startY + registerHeight + classicalRegHeight * 2 }, - ], - }, - 2: { - type: RegisterType.Qubit, - y: startY + registerHeight + classicalRegHeight * 3, - children: [{ type: RegisterType.Classical, y: startY + registerHeight + classicalRegHeight * 4 }], - }, - }; - measureGates = [ - { - type: GateType.Measure, - x: startX, - controlsY: [startY], - targetsY: [startY + classicalRegHeight], - label: '', - width: minGateWidth, - }, - { - type: GateType.Measure, - x: startX, - controlsY: [startY], - targetsY: [startY + classicalRegHeight * 2], - label: '', - width: minGateWidth, - }, - { - type: GateType.Measure, - x: startX, - controlsY: [startY + classicalRegHeight * 3], - targetsY: [startY + classicalRegHeight * 4], - label: '', - width: minGateWidth, - }, - ]; - // Normal width - expect(formatRegisters(registers, measureGates, startX + 100)).toMatchSnapshot(); - // Small width - expect(formatRegisters(registers, measureGates, startX + 5)).toMatchSnapshot(); - // Large width - expect(formatRegisters(registers, measureGates, startX + 500)).toMatchSnapshot(); - }); + registers = { + 0: { type: RegisterType.Qubit, y: startY }, + 1: { + type: RegisterType.Qubit, + y: startY + registerHeight, + children: [ + { + type: RegisterType.Classical, + y: startY + registerHeight + classicalRegHeight, + }, + { + type: RegisterType.Classical, + y: startY + registerHeight + classicalRegHeight * 2, + }, + ], + }, + 2: { + type: RegisterType.Qubit, + y: startY + registerHeight + classicalRegHeight * 3, + children: [ + { + type: RegisterType.Classical, + y: startY + registerHeight + classicalRegHeight * 4, + }, + ], + }, + }; + measureGates = [ + { + type: GateType.Measure, + x: startX, + controlsY: [startY], + targetsY: [startY + classicalRegHeight], + label: "", + width: minGateWidth, + }, + { + type: GateType.Measure, + x: startX, + controlsY: [startY], + targetsY: [startY + classicalRegHeight * 2], + label: "", + width: minGateWidth, + }, + { + type: GateType.Measure, + x: startX, + controlsY: [startY + classicalRegHeight * 3], + targetsY: [startY + classicalRegHeight * 4], + label: "", + width: minGateWidth, + }, + ]; + // Normal width + expect( + formatRegisters(registers, measureGates, startX + 100), + ).toMatchSnapshot(); + // Small width + expect( + formatRegisters(registers, measureGates, startX + 5), + ).toMatchSnapshot(); + // Large width + expect( + formatRegisters(registers, measureGates, startX + 500), + ).toMatchSnapshot(); + }); }); diff --git a/circuit_vis/__tests__/utils.test.ts b/circuit_vis/__tests__/utils.test.ts index 23889c0b77..1287d67060 100644 --- a/circuit_vis/__tests__/utils.test.ts +++ b/circuit_vis/__tests__/utils.test.ts @@ -1,51 +1,81 @@ -import { getGateWidth, _getStringWidth, createUUID } from '../src/utils'; -import { minGateWidth, labelPadding } from '../src/constants'; -import { GateType } from '../src/metadata'; +import { getGateWidth, _getStringWidth, createUUID } from "../src/utils"; +import { minGateWidth, labelPadding } from "../src/constants"; +import { GateType } from "../src/metadata"; -describe('Testing createUUID', () => { - test('no x in uuid', () => expect(createUUID()).not.toContain('x')); - test('no y in uuid', () => expect(createUUID()).not.toContain('y')); +describe("Testing createUUID", () => { + test("no x in uuid", () => expect(createUUID()).not.toContain("x")); + test("no y in uuid", () => expect(createUUID()).not.toContain("y")); }); -describe('Testing getGateWidth', () => { - test('measure gate', () => - expect(getGateWidth(Object.assign({ type: GateType.Measure, label: '' }))).toEqual(minGateWidth)); - test('cnot gate', () => - expect(getGateWidth(Object.assign({ type: GateType.Cnot, label: 'x' }))).toEqual(minGateWidth)); - test('swap gate', () => - expect(getGateWidth(Object.assign({ type: GateType.Swap, label: '' }))).toEqual(minGateWidth)); - test('single unitary gate', () => - expect(getGateWidth(Object.assign({ type: GateType.Unitary, label: 'x' }))).toEqual(minGateWidth)); - test('multi unitary gate', () => - expect(getGateWidth(Object.assign({ type: GateType.Unitary, label: 'zz' }))).toEqual(minGateWidth)); - test('unitary gate with arguments', () => - expect(getGateWidth(Object.assign({ type: GateType.Unitary, displayArgs: '(0.25)', label: 'RX' }))).toEqual( - 52, - )); - test('invalid', () => - expect(getGateWidth(Object.assign({ type: GateType.Invalid, label: '' }))).toEqual(minGateWidth)); - test('unitary with long name', () => - expect(getGateWidth(Object.assign({ type: GateType.Unitary, label: 'FOOBAR' }))).toBeCloseTo( - 59 + labelPadding * 2, - )); - test('classically controlled gate', () => { - expect(getGateWidth(Object.assign({ type: GateType.ClassicalControlled, label: '', width: 500 }))).toEqual(500); - }); +describe("Testing getGateWidth", () => { + test("measure gate", () => + expect( + getGateWidth(Object.assign({ type: GateType.Measure, label: "" })), + ).toEqual(minGateWidth)); + test("cnot gate", () => + expect( + getGateWidth(Object.assign({ type: GateType.Cnot, label: "x" })), + ).toEqual(minGateWidth)); + test("swap gate", () => + expect( + getGateWidth(Object.assign({ type: GateType.Swap, label: "" })), + ).toEqual(minGateWidth)); + test("single unitary gate", () => + expect( + getGateWidth(Object.assign({ type: GateType.Unitary, label: "x" })), + ).toEqual(minGateWidth)); + test("multi unitary gate", () => + expect( + getGateWidth(Object.assign({ type: GateType.Unitary, label: "zz" })), + ).toEqual(minGateWidth)); + test("unitary gate with arguments", () => + expect( + getGateWidth( + Object.assign({ + type: GateType.Unitary, + displayArgs: "(0.25)", + label: "RX", + }), + ), + ).toEqual(52)); + test("invalid", () => + expect( + getGateWidth(Object.assign({ type: GateType.Invalid, label: "" })), + ).toEqual(minGateWidth)); + test("unitary with long name", () => + expect( + getGateWidth(Object.assign({ type: GateType.Unitary, label: "FOOBAR" })), + ).toBeCloseTo(59 + labelPadding * 2)); + test("classically controlled gate", () => { + expect( + getGateWidth( + Object.assign({ + type: GateType.ClassicalControlled, + label: "", + width: 500, + }), + ), + ).toEqual(500); + }); }); -describe('Testing _getStringWidth', () => { - test('correctly scaled width with font size', () => { - expect(_getStringWidth('FOOBAR', 14)).toEqual(59); - expect(_getStringWidth('FOOBAR', 20)).toEqual(84); - expect(_getStringWidth('FOOBAR', 5)).toEqual(21); - expect(_getStringWidth('FOOBAR', 100)).toEqual(423); - expect(_getStringWidth('FOOBAR', 200)).toEqual(844); - }); +describe("Testing _getStringWidth", () => { + test("correctly scaled width with font size", () => { + expect(_getStringWidth("FOOBAR", 14)).toEqual(59); + expect(_getStringWidth("FOOBAR", 20)).toEqual(84); + expect(_getStringWidth("FOOBAR", 5)).toEqual(21); + expect(_getStringWidth("FOOBAR", 100)).toEqual(423); + expect(_getStringWidth("FOOBAR", 200)).toEqual(844); + }); - test('varying size strings', () => { - expect(_getStringWidth('H', 14)).toBeGreaterThanOrEqual(9); - expect(_getStringWidth('H', 14)).toBeLessThanOrEqual(10); - expect(_getStringWidth('GateWithASuperLongName', 14)).toBeGreaterThanOrEqual(174); - expect(_getStringWidth('GateWithASuperLongName', 14)).toBeLessThanOrEqual(176); - }); + test("varying size strings", () => { + expect(_getStringWidth("H", 14)).toBeGreaterThanOrEqual(9); + expect(_getStringWidth("H", 14)).toBeLessThanOrEqual(10); + expect( + _getStringWidth("GateWithASuperLongName", 14), + ).toBeGreaterThanOrEqual(174); + expect(_getStringWidth("GateWithASuperLongName", 14)).toBeLessThanOrEqual( + 176, + ); + }); }); diff --git a/circuit_vis/example/circuits.js b/circuit_vis/example/circuits.js index 8345e82615..278218e39e 100644 --- a/circuit_vis/example/circuits.js +++ b/circuit_vis/example/circuits.js @@ -6,1666 +6,1681 @@ // Basic example: entanglement with measurement //export const entangle = { - qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], - operations: [ + qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], + operations: [ + { + gate: "H", + targets: [{ qId: 0 }], + }, + { + gate: "X", + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + }, + { + gate: "Measure", + isMeasurement: true, + controls: [{ qId: 1 }], + targets: [{ type: 1, qId: 1, cId: 0 }], + }, + ], +}; + +// Sample circuit +//export +const sample = { + qubits: [{ id: 0, numChildren: 1 }, { id: 1 }, { id: 2 }, { id: 3 }], + operations: [ + { + gate: "Foo", + conditionalRender: 3, + targets: [{ qId: 0 }, { qId: 1 }], + children: [ { - gate: 'H', - targets: [{ qId: 0 }], + gate: "H", + targets: [{ qId: 1 }], }, { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], + gate: "RX", + displayArgs: "(0.25)", + isControlled: true, + controls: [{ qId: 1 }], + targets: [{ qId: 0 }], }, + ], + }, + { + gate: "X", + targets: [{ qId: 3 }], + }, + { + gate: "X", + isControlled: true, + controls: [{ qId: 1 }], + targets: [{ qId: 2 }, { qId: 3 }], + }, + { + gate: "X", + isControlled: true, + controls: [{ qId: 2 }, { qId: 3 }], + targets: [{ qId: 1 }], + }, + { + gate: "X", + isControlled: true, + controls: [{ qId: 1 }, { qId: 3 }], + targets: [{ qId: 2 }], + }, + { + gate: "X", + isControlled: true, + controls: [{ qId: 2 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: "measure", + isMeasurement: true, + controls: [{ qId: 0 }], + targets: [{ type: 1, qId: 0, cId: 0 }], + }, + { + gate: "ApplyIfElseR", + isConditional: true, + controls: [{ type: 1, qId: 0, cId: 0 }], + targets: [], + children: [ { - gate: 'Measure', - isMeasurement: true, - controls: [{ qId: 1 }], - targets: [{ type: 1, qId: 1, cId: 0 }], + gate: "H", + targets: [{ qId: 1 }], + conditionalRender: 1, }, - ], -}; - -// Sample circuit -//export -const sample = { - qubits: [{ id: 0, numChildren: 1 }, { id: 1 }, { id: 2 }, { id: 3 }], - operations: [ { - gate: 'Foo', - conditionalRender: 3, - targets: [{ qId: 0 }, { qId: 1 }], - children: [ - { - gate: 'H', - targets: [{ qId: 1 }], - }, - { - gate: 'RX', - displayArgs: '(0.25)', - isControlled: true, - controls: [{ qId: 1 }], - targets: [{ qId: 0 }], - }, - ], + gate: "X", + targets: [{ qId: 1 }], + conditionalRender: 1, }, { - gate: 'X', - targets: [{ qId: 3 }], + gate: "X", + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + conditionalRender: 2, }, { - gate: 'X', - isControlled: true, - controls: [{ qId: 1 }], - targets: [{ qId: 2 }, { qId: 3 }], + gate: "Foo", + targets: [{ qId: 3 }], + conditionalRender: 2, }, + ], + }, + { + gate: "SWAP", + targets: [{ qId: 0 }, { qId: 2 }], + children: [ { - gate: 'X', - isControlled: true, - controls: [{ qId: 2 }, { qId: 3 }], - targets: [{ qId: 1 }], + gate: "X", + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 2 }], }, { - gate: 'X', - isControlled: true, - controls: [{ qId: 1 }, { qId: 3 }], - targets: [{ qId: 2 }], + gate: "X", + isControlled: true, + controls: [{ qId: 2 }], + targets: [{ qId: 0 }], }, { - gate: 'X', - isControlled: true, - controls: [{ qId: 2 }], - targets: [{ qId: 1 }, { qId: 3 }], + gate: "X", + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 2 }], }, + ], + }, + { + gate: "ZZ", + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: "ZZ", + targets: [{ qId: 0 }, { qId: 1 }], + }, + { + gate: "XX", + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: "XX", + isControlled: true, + controls: [{ qId: 2 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: "XX", + isControlled: true, + controls: [{ qId: 0 }, { qId: 2 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + ], +}; + +// Teleportation algorithm +//export +const teleport = { + qubits: [ + { + id: 0, + numChildren: 1, + }, + { + id: 1, + numChildren: 1, + }, + { + id: 2, + }, + ], + operations: [ + { + gate: "Teleport", + children: [ { - gate: 'measure', - isMeasurement: true, - controls: [{ qId: 0 }], - targets: [{ type: 1, qId: 0, cId: 0 }], + gate: "Entangle", + children: [ + { + gate: "H", + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: "X", + isControlled: true, + controls: [ + { + qId: 1, + }, + ], + targets: [ + { + qId: 2, + }, + ], + }, + ], + targets: [ + { + qId: 1, + }, + { + qId: 2, + }, + ], }, { - gate: 'ApplyIfElseR', - isConditional: true, - controls: [{ type: 1, qId: 0, cId: 0 }], - targets: [], - children: [ + gate: "PrepareMessage", + children: [ + { + gate: "Random", + displayArgs: "([0.5, 0.5])", + children: [ { - gate: 'H', - targets: [{ qId: 1 }], - conditionalRender: 1, + gate: "DrawCategorical", + displayArgs: "([0.5, 0.5])", + children: [ + { + gate: "DrawRandomDouble", + displayArgs: "(0, 1)", + targets: [], + }, + ], + targets: [], }, + ], + targets: [], + }, + { + gate: "SetPlus", + children: [ + { + gate: "H", + targets: [ + { + qId: 0, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: "Encode", + children: [ + { + gate: "X", + isControlled: true, + controls: [ { - gate: 'X', - targets: [{ qId: 1 }], - conditionalRender: 1, + qId: 0, }, + ], + targets: [ { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - conditionalRender: 2, + qId: 1, }, + ], + }, + { + gate: "H", + targets: [ { - gate: 'Foo', - targets: [{ qId: 3 }], - conditionalRender: 2, + qId: 0, }, - ], + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + ], }, { - gate: 'SWAP', - targets: [{ qId: 0 }, { qId: 2 }], - children: [ - { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, - { gate: 'X', isControlled: true, controls: [{ qId: 2 }], targets: [{ qId: 0 }] }, - { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, - ], + gate: "M", + isMeasurement: true, + controls: [ + { + qId: 0, + }, + ], + targets: [ + { + type: 1, + qId: 0, + cId: 0, + }, + ], }, { - gate: 'ZZ', - targets: [{ qId: 1 }, { qId: 3 }], + gate: "measure", + isMeasurement: true, + controls: [ + { + qId: 1, + }, + ], + targets: [ + { + type: 1, + qId: 1, + cId: 0, + }, + ], }, { - gate: 'ZZ', - targets: [{ qId: 0 }, { qId: 1 }], + gate: "Decode", + children: [ + { + gate: "ApplyIfElseR", + isConditional: true, + controls: [ + { + type: 1, + qId: 1, + cId: 0, + }, + ], + targets: [], + children: [ + { + gate: "X", + controls: [ + { + type: 1, + qId: 1, + cId: 0, + }, + ], + targets: [ + { + qId: 2, + }, + ], + conditionalRender: 2, + }, + ], + }, + { + gate: "ApplyIfElseR", + isConditional: true, + controls: [ + { + type: 1, + qId: 0, + cId: 0, + }, + ], + targets: [], + children: [ + { + gate: "Z", + controls: [ + { + type: 1, + qId: 0, + cId: 0, + }, + ], + targets: [ + { + qId: 2, + }, + ], + conditionalRender: 2, + }, + ], + }, + ], + controls: [ + { + type: 1, + qId: 0, + cId: 0, + }, + { + type: 1, + qId: 1, + cId: 0, + }, + ], + targets: [ + { + qId: 2, + }, + ], }, + ], + targets: [ { - gate: 'XX', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }, { qId: 3 }], + qId: 1, }, { - gate: 'XX', - isControlled: true, - controls: [{ qId: 2 }], - targets: [{ qId: 1 }, { qId: 3 }], + qId: 2, }, { - gate: 'XX', - isControlled: true, - controls: [{ qId: 0 }, { qId: 2 }], - targets: [{ qId: 1 }, { qId: 3 }], + qId: 0, }, - ], + ], + }, + ], }; -// Teleportation algorithm +// Grover's algorithm //export -const teleport = { - qubits: [ - { - id: 0, - numChildren: 1, - }, - { - id: 1, - numChildren: 1, - }, +const grover = { + qubits: [ + { + id: 0, + numChildren: 1, + }, + { + id: 1, + numChildren: 1, + }, + { + id: 2, + numChildren: 1, + }, + { + id: 3, + numChildren: 1, + }, + { + id: 4, + }, + ], + operations: [ + { + gate: "GroverSearch", + children: [ { - id: 2, + gate: "PrepareSuperposition", + children: [ + { + gate: "H", + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: "H", + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: "H", + targets: [ + { + qId: 2, + }, + ], + }, + { + gate: "H", + targets: [ + { + qId: 3, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + ], }, - ], - operations: [ { - gate: 'Teleport', - children: [ - { - gate: 'Entangle', - children: [ - { - gate: 'H', - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: 'X', - isControlled: true, - controls: [ - { - qId: 1, - }, - ], - targets: [ - { - qId: 2, - }, - ], + gate: "GroverIteration", + displayArgs: "(Oracle)", + children: [ + { + gate: "Oracle", + displayArgs: "(Oracle_6)", + children: [ + { + gate: "X", + targets: [ + { + qId: 4, + }, + ], + }, + { + gate: "H", + targets: [ + { + qId: 4, + }, + ], + }, + { + gate: "Oracle_6", + children: [ + { + gate: "X", + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: "X", + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: "X", + isControlled: true, + controls: [ + { + qId: 0, }, - ], - targets: [ { - qId: 1, - }, + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + ], + targets: [ { - qId: 2, + qId: 4, }, - ], + ], + }, + { + gate: "X", + isAdjoint: true, + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: "X", + isAdjoint: true, + targets: [ + { + qId: 0, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + { + qId: 4, + }, + ], }, { - gate: 'PrepareMessage', - children: [ + gate: "H", + isAdjoint: true, + targets: [ + { + qId: 4, + }, + ], + }, + { + gate: "X", + isAdjoint: true, + targets: [ + { + qId: 4, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + { + qId: 4, + }, + ], + }, + { + gate: "Diffuser", + children: [ + { + gate: "H", + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: "H", + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: "H", + targets: [ + { + qId: 2, + }, + ], + }, + { + gate: "H", + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: "ConditionalPhaseFlip", + children: [ + { + gate: "X", + targets: [ { - gate: 'Random', - displayArgs: '([0.5, 0.5])', - children: [ - { - gate: 'DrawCategorical', - displayArgs: '([0.5, 0.5])', - children: [ - { - gate: 'DrawRandomDouble', - displayArgs: '(0, 1)', - targets: [], - }, - ], - targets: [], - }, - ], - targets: [], + qId: 0, }, + ], + }, + { + gate: "X", + targets: [ { - gate: 'SetPlus', - children: [ - { - gate: 'H', - targets: [ - { - qId: 0, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: 'Encode', - children: [ - { - gate: 'X', - isControlled: true, - controls: [ - { - qId: 0, - }, - ], - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: 'H', - targets: [ - { - qId: 0, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - ], - }, - { - gate: 'M', - isMeasurement: true, - controls: [ - { - qId: 0, - }, - ], - targets: [ - { - type: 1, - qId: 0, - cId: 0, - }, - ], - }, - { - gate: 'measure', - isMeasurement: true, - controls: [ - { - qId: 1, - }, - ], - targets: [ - { - type: 1, - qId: 1, - cId: 0, - }, - ], - }, - { - gate: 'Decode', - children: [ - { - gate: 'ApplyIfElseR', - isConditional: true, - controls: [ - { - type: 1, - qId: 1, - cId: 0, - }, - ], - targets: [], - children: [ - { - gate: 'X', - controls: [ - { - type: 1, - qId: 1, - cId: 0, - }, - ], - targets: [ - { - qId: 2, - }, - ], - conditionalRender: 2, - }, - ], + qId: 1, }, + ], + }, + { + gate: "X", + targets: [ { - gate: 'ApplyIfElseR', - isConditional: true, - controls: [ - { - type: 1, - qId: 0, - cId: 0, - }, - ], - targets: [], - children: [ - { - gate: 'Z', - controls: [ - { - type: 1, - qId: 0, - cId: 0, - }, - ], - targets: [ - { - qId: 2, - }, - ], - conditionalRender: 2, - }, - ], + qId: 2, }, - ], - controls: [ + ], + }, + { + gate: "X", + targets: [ { - type: 1, - qId: 0, - cId: 0, - }, - { - type: 1, - qId: 1, - cId: 0, - }, - ], - targets: [ - { - qId: 2, - }, - ], - }, - ], - targets: [ - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 0, - }, - ], - }, - ], -}; - -// Grover's algorithm -//export -const grover = { - qubits: [ - { - id: 0, - numChildren: 1, - }, - { - id: 1, - numChildren: 1, - }, - { - id: 2, - numChildren: 1, - }, - { - id: 3, - numChildren: 1, - }, - { - id: 4, - }, - ], - operations: [ - { - gate: 'GroverSearch', - children: [ - { - gate: 'PrepareSuperposition', - children: [ - { - gate: 'H', - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: 'H', - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: 'H', - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: 'H', - targets: [ - { - qId: 3, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - }, - { - gate: 'GroverIteration', - displayArgs: '(Oracle)', - children: [ - { - gate: 'Oracle', - displayArgs: '(Oracle_6)', - children: [ - { - gate: 'X', - targets: [ - { - qId: 4, - }, - ], - }, - { - gate: 'H', - targets: [ - { - qId: 4, - }, - ], - }, - { - gate: 'Oracle_6', - children: [ - { - gate: 'X', - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: 'X', - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: 'X', - isControlled: true, - controls: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - targets: [ - { - qId: 4, - }, - ], - }, - { - gate: 'X', - isAdjoint: true, - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: 'X', - isAdjoint: true, - targets: [ - { - qId: 0, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - { - qId: 4, - }, - ], - }, - { - gate: 'H', - isAdjoint: true, - targets: [ - { - qId: 4, - }, - ], - }, - { - gate: 'X', - isAdjoint: true, - targets: [ - { - qId: 4, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - { - qId: 4, - }, - ], - }, - { - gate: 'Diffuser', - children: [ - { - gate: 'H', - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: 'H', - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: 'H', - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: 'H', - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: 'ConditionalPhaseFlip', - children: [ - { - gate: 'X', - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: 'X', - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: 'X', - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: 'X', - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: 'Z', - isControlled: true, - controls: [ - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: 'R', - displayArgs: '(PauliI, 3.141592653589793)', - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: 'X', - isAdjoint: true, - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: 'X', - isAdjoint: true, - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: 'X', - isAdjoint: true, - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: 'X', - isAdjoint: true, - targets: [ - { - qId: 0, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - }, - { - gate: 'H', - isAdjoint: true, - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: 'H', - isAdjoint: true, - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: 'H', - isAdjoint: true, - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: 'H', - isAdjoint: true, - targets: [ - { - qId: 0, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - { - qId: 4, - }, - ], - }, - { - gate: 'GroverIteration', - displayArgs: '(Oracle)', - children: [ - { - gate: 'Oracle', - displayArgs: '(Oracle_6)', - children: [ - { - gate: 'X', - targets: [ - { - qId: 4, - }, - ], - }, - { - gate: 'H', - targets: [ - { - qId: 4, - }, - ], - }, - { - gate: 'Oracle_6', - children: [ - { - gate: 'X', - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: 'X', - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: 'X', - isControlled: true, - controls: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - targets: [ - { - qId: 4, - }, - ], - }, - { - gate: 'X', - isAdjoint: true, - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: 'X', - isAdjoint: true, - targets: [ - { - qId: 0, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - { - qId: 4, - }, - ], - }, - { - gate: 'H', - isAdjoint: true, - targets: [ - { - qId: 4, - }, - ], - }, - { - gate: 'X', - isAdjoint: true, - targets: [ - { - qId: 4, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - { - qId: 4, - }, - ], - }, - { - gate: 'Diffuser', - children: [ - { - gate: 'H', - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: 'H', - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: 'H', - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: 'H', - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: 'ConditionalPhaseFlip', - children: [ - { - gate: 'X', - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: 'X', - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: 'X', - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: 'X', - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: 'Z', - isControlled: true, - controls: [ - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: 'R', - displayArgs: '(PauliI, 3.141592653589793)', - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: 'X', - isAdjoint: true, - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: 'X', - isAdjoint: true, - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: 'X', - isAdjoint: true, - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: 'X', - isAdjoint: true, - targets: [ - { - qId: 0, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - }, - { - gate: 'H', - isAdjoint: true, - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: 'H', - isAdjoint: true, - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: 'H', - isAdjoint: true, - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: 'H', - isAdjoint: true, - targets: [ - { - qId: 0, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - { - qId: 4, - }, - ], - }, - { - gate: 'GroverIteration', - displayArgs: '(Oracle)', - children: [ - { - gate: 'Oracle', - displayArgs: '(Oracle_6)', - children: [ - { - gate: 'X', - targets: [ - { - qId: 4, - }, - ], - }, - { - gate: 'H', - targets: [ - { - qId: 4, - }, - ], - }, - { - gate: 'Oracle_6', - children: [ - { - gate: 'X', - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: 'X', - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: 'X', - isControlled: true, - controls: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - targets: [ - { - qId: 4, - }, - ], - }, - { - gate: 'X', - isAdjoint: true, - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: 'X', - isAdjoint: true, - targets: [ - { - qId: 0, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - { - qId: 4, - }, - ], - }, - { - gate: 'H', - isAdjoint: true, - targets: [ - { - qId: 4, - }, - ], - }, - { - gate: 'X', - isAdjoint: true, - targets: [ - { - qId: 4, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - { - qId: 4, - }, - ], - }, - { - gate: 'Diffuser', - children: [ - { - gate: 'H', - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: 'H', - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: 'H', - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: 'H', - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: 'ConditionalPhaseFlip', - children: [ - { - gate: 'X', - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: 'X', - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: 'X', - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: 'X', - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: 'Z', - isControlled: true, - controls: [ - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: 'R', - displayArgs: '(PauliI, 3.141592653589793)', - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: 'X', - isAdjoint: true, - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: 'X', - isAdjoint: true, - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: 'X', - isAdjoint: true, - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: 'X', - isAdjoint: true, - targets: [ - { - qId: 0, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - }, - { - gate: 'H', - isAdjoint: true, - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: 'H', - isAdjoint: true, - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: 'H', - isAdjoint: true, - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: 'H', - isAdjoint: true, - targets: [ - { - qId: 0, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, + qId: 3, + }, + ], + }, + { + gate: "Z", + isControlled: true, + controls: [ + { + qId: 1, + }, + { + qId: 2, + }, { - qId: 4, + qId: 3, }, - ], + ], + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: "R", + displayArgs: "(PauliI, 3.141592653589793)", + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: "X", + isAdjoint: true, + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: "X", + isAdjoint: true, + targets: [ + { + qId: 2, + }, + ], + }, + { + gate: "X", + isAdjoint: true, + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: "X", + isAdjoint: true, + targets: [ + { + qId: 0, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + ], + }, + { + gate: "H", + isAdjoint: true, + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: "H", + isAdjoint: true, + targets: [ + { + qId: 2, + }, + ], + }, + { + gate: "H", + isAdjoint: true, + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: "H", + isAdjoint: true, + targets: [ + { + qId: 0, + }, + ], }, + ], + targets: [ { - gate: 'M', - isMeasurement: true, - controls: [ + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + { + qId: 4, + }, + ], + }, + { + gate: "GroverIteration", + displayArgs: "(Oracle)", + children: [ + { + gate: "Oracle", + displayArgs: "(Oracle_6)", + children: [ + { + gate: "X", + targets: [ + { + qId: 4, + }, + ], + }, + { + gate: "H", + targets: [ + { + qId: 4, + }, + ], + }, + { + gate: "Oracle_6", + children: [ + { + gate: "X", + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: "X", + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: "X", + isControlled: true, + controls: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, { - qId: 0, + qId: 3, }, - ], - targets: [ + ], + targets: [ { - type: 1, - qId: 0, - cId: 0, + qId: 4, }, - ], + ], + }, + { + gate: "X", + isAdjoint: true, + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: "X", + isAdjoint: true, + targets: [ + { + qId: 0, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + { + qId: 4, + }, + ], + }, + { + gate: "H", + isAdjoint: true, + targets: [ + { + qId: 4, + }, + ], + }, + { + gate: "X", + isAdjoint: true, + targets: [ + { + qId: 4, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + { + qId: 4, + }, + ], + }, + { + gate: "Diffuser", + children: [ + { + gate: "H", + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: "H", + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: "H", + targets: [ + { + qId: 2, + }, + ], + }, + { + gate: "H", + targets: [ + { + qId: 3, + }, + ], }, { - gate: 'M', - isMeasurement: true, - controls: [ + gate: "ConditionalPhaseFlip", + children: [ + { + gate: "X", + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: "X", + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: "X", + targets: [ { - qId: 1, + qId: 2, }, - ], - targets: [ + ], + }, + { + gate: "X", + targets: [ { - type: 1, - qId: 1, - cId: 0, + qId: 3, }, - ], + ], + }, + { + gate: "Z", + isControlled: true, + controls: [ + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + ], + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: "R", + displayArgs: "(PauliI, 3.141592653589793)", + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: "X", + isAdjoint: true, + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: "X", + isAdjoint: true, + targets: [ + { + qId: 2, + }, + ], + }, + { + gate: "X", + isAdjoint: true, + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: "X", + isAdjoint: true, + targets: [ + { + qId: 0, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + ], + }, + { + gate: "H", + isAdjoint: true, + targets: [ + { + qId: 3, + }, + ], }, { - gate: 'M', - isMeasurement: true, - controls: [ + gate: "H", + isAdjoint: true, + targets: [ + { + qId: 2, + }, + ], + }, + { + gate: "H", + isAdjoint: true, + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: "H", + isAdjoint: true, + targets: [ + { + qId: 0, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + { + qId: 4, + }, + ], + }, + { + gate: "GroverIteration", + displayArgs: "(Oracle)", + children: [ + { + gate: "Oracle", + displayArgs: "(Oracle_6)", + children: [ + { + gate: "X", + targets: [ + { + qId: 4, + }, + ], + }, + { + gate: "H", + targets: [ + { + qId: 4, + }, + ], + }, + { + gate: "Oracle_6", + children: [ + { + gate: "X", + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: "X", + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: "X", + isControlled: true, + controls: [ { - qId: 2, + qId: 0, }, - ], - targets: [ { - type: 1, - qId: 2, - cId: 0, + qId: 1, }, - ], + { + qId: 2, + }, + { + qId: 3, + }, + ], + targets: [ + { + qId: 4, + }, + ], + }, + { + gate: "X", + isAdjoint: true, + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: "X", + isAdjoint: true, + targets: [ + { + qId: 0, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + { + qId: 4, + }, + ], + }, + { + gate: "H", + isAdjoint: true, + targets: [ + { + qId: 4, + }, + ], + }, + { + gate: "X", + isAdjoint: true, + targets: [ + { + qId: 4, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, }, { - gate: 'M', - isMeasurement: true, - controls: [ + qId: 3, + }, + { + qId: 4, + }, + ], + }, + { + gate: "Diffuser", + children: [ + { + gate: "H", + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: "H", + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: "H", + targets: [ + { + qId: 2, + }, + ], + }, + { + gate: "H", + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: "ConditionalPhaseFlip", + children: [ + { + gate: "X", + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: "X", + targets: [ + { + qId: 1, + }, + ], + }, + { + gate: "X", + targets: [ + { + qId: 2, + }, + ], + }, + { + gate: "X", + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: "Z", + isControlled: true, + controls: [ + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + ], + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: "R", + displayArgs: "(PauliI, 3.141592653589793)", + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: "X", + isAdjoint: true, + targets: [ + { + qId: 3, + }, + ], + }, + { + gate: "X", + isAdjoint: true, + targets: [ + { + qId: 2, + }, + ], + }, + { + gate: "X", + isAdjoint: true, + targets: [ { - qId: 3, + qId: 1, }, - ], - targets: [ + ], + }, + { + gate: "X", + isAdjoint: true, + targets: [ { - type: 1, - qId: 3, - cId: 0, + qId: 0, }, - ], + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + ], }, - ], - targets: [ { - qId: 0, + gate: "H", + isAdjoint: true, + targets: [ + { + qId: 3, + }, + ], }, { - qId: 1, + gate: "H", + isAdjoint: true, + targets: [ + { + qId: 2, + }, + ], }, { - qId: 2, + gate: "H", + isAdjoint: true, + targets: [ + { + qId: 1, + }, + ], }, { - qId: 3, + gate: "H", + isAdjoint: true, + targets: [ + { + qId: 0, + }, + ], }, + ], + targets: [ { - qId: 4, + qId: 0, }, - ], + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + { + qId: 4, + }, + ], + }, + { + gate: "M", + isMeasurement: true, + controls: [ + { + qId: 0, + }, + ], + targets: [ + { + type: 1, + qId: 0, + cId: 0, + }, + ], + }, + { + gate: "M", + isMeasurement: true, + controls: [ + { + qId: 1, + }, + ], + targets: [ + { + type: 1, + qId: 1, + cId: 0, + }, + ], + }, + { + gate: "M", + isMeasurement: true, + controls: [ + { + qId: 2, + }, + ], + targets: [ + { + type: 1, + qId: 2, + cId: 0, + }, + ], + }, + { + gate: "M", + isMeasurement: true, + controls: [ + { + qId: 3, + }, + ], + targets: [ + { + type: 1, + qId: 3, + cId: 0, + }, + ], + }, + ], + targets: [ + { + qId: 0, + }, + { + qId: 1, + }, + { + qId: 2, + }, + { + qId: 3, + }, + { + qId: 4, }, - ], + ], + }, + ], }; diff --git a/circuit_vis/example/index.html b/circuit_vis/example/index.html index c3060fdda3..fb51ec5016 100644 --- a/circuit_vis/example/index.html +++ b/circuit_vis/example/index.html @@ -1,58 +1,55 @@ - + - - - - - + + + + quantum-viz.js Demo - + - +
-

quantum-viz.js

-
- Please make sure the project is built first by following the - Running from source instructions from the README.md -
- -
-

1. Entangle

-
-
-

2. Sample

-
-

3. Teleport

-
-

4. Grover

-
-
+

quantum-viz.js

+
+ Please make sure the project is built first by following the + Running from source instructions from the README.md +
+ +
+

1. Entangle

+
+

2. Sample

+
+

3. Teleport

+
+

4. Grover

+
+
- - + diff --git a/circuit_vis/example/script.js b/circuit_vis/example/script.js index f6d62df9f7..d1c5ff63c4 100644 --- a/circuit_vis/example/script.js +++ b/circuit_vis/example/script.js @@ -1,29 +1,29 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -if (typeof qviz != 'undefined') { - document.getElementById('message').remove(); +if (typeof qviz != "undefined") { + document.getElementById("message").remove(); - /* These examples shows how to draw circuits into containers. */ - const entangleDiv = document.getElementById('entangle'); - if (entangleDiv != null) { - qviz.draw(entangle, entangleDiv, qviz.STYLES['Default']); - } + /* These examples shows how to draw circuits into containers. */ + const entangleDiv = document.getElementById("entangle"); + if (entangleDiv != null) { + qviz.draw(entangle, entangleDiv, qviz.STYLES["Default"]); + } - const sampleDiv = document.getElementById('sample'); - if (sampleDiv != null) { - qviz.draw(sample, sampleDiv, qviz.STYLES['Default']); - } + const sampleDiv = document.getElementById("sample"); + if (sampleDiv != null) { + qviz.draw(sample, sampleDiv, qviz.STYLES["Default"]); + } - const teleportDiv = document.getElementById('teleport'); - if (teleportDiv != null) { - qviz.draw(teleport, teleportDiv, qviz.STYLES['Default']); - } + const teleportDiv = document.getElementById("teleport"); + if (teleportDiv != null) { + qviz.draw(teleport, teleportDiv, qviz.STYLES["Default"]); + } - const groverDiv = document.getElementById('grover'); - if (groverDiv != null) { - qviz.draw(grover, groverDiv, qviz.STYLES['Default']); - } + const groverDiv = document.getElementById("grover"); + if (groverDiv != null) { + qviz.draw(grover, groverDiv, qviz.STYLES["Default"]); + } } else { - document.getElementById('group').remove(); + document.getElementById("group").remove(); } diff --git a/circuit_vis/jest.config.js b/circuit_vis/jest.config.js index c0432e2a85..49bd84ae2d 100644 --- a/circuit_vis/jest.config.js +++ b/circuit_vis/jest.config.js @@ -1,8 +1,8 @@ module.exports = { - roots: [''], - transform: { - '^.+\\.tsx?$': 'ts-jest', - }, - testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$', - moduleFileExtensions: ['ts', 'js'], + roots: [""], + transform: { + "^.+\\.tsx?$": "ts-jest", + }, + testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$", + moduleFileExtensions: ["ts", "js"], }; diff --git a/circuit_vis/src/circuit.ts b/circuit_vis/src/circuit.ts index 685215e3f3..584069a785 100644 --- a/circuit_vis/src/circuit.ts +++ b/circuit_vis/src/circuit.ts @@ -1,72 +1,72 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { Register } from './register'; +import { Register } from "./register"; /** * Circuit to be visualized. */ export interface Circuit { - /** Array of qubit resources. */ - qubits: Qubit[]; - operations: Operation[]; + /** Array of qubit resources. */ + qubits: Qubit[]; + operations: Operation[]; } /** * Represents a unique qubit resource bit. */ export interface Qubit { - /** Qubit ID. */ - id: number; - /** Number of classical registers attached to quantum register. */ - numChildren?: number; + /** Qubit ID. */ + id: number; + /** Number of classical registers attached to quantum register. */ + numChildren?: number; } /** * Conditions on when to render the given operation. */ export enum ConditionalRender { - /** Always rendered. */ - Always, - /** Render classically-controlled operation when measurement is a zero. */ - OnZero, - /** Render classically-controlled operation when measurement is a one. */ - OnOne, - /** Render operation as a group of its nested operations. */ - AsGroup, + /** Always rendered. */ + Always, + /** Render classically-controlled operation when measurement is a zero. */ + OnZero, + /** Render classically-controlled operation when measurement is a one. */ + OnOne, + /** Render operation as a group of its nested operations. */ + AsGroup, } /** * Custom data attributes (e.g. data-{attr}="{val}") */ export interface DataAttributes { - [attr: string]: string; + [attr: string]: string; } /** * Represents an operation and the registers it acts on. */ export interface Operation { - /** Gate label. */ - gate: string; - /** Formatted gate arguments to be displayed. */ - displayArgs?: string; - /** Nested operations within this operation. */ - children?: Operation[]; - /** Whether gate is a measurement operation. */ - isMeasurement: boolean; - /** Whether gate is a conditional operation. */ - isConditional: boolean; - /** Whether gate is a controlled operation. */ - isControlled: boolean; - /** Whether gate is an adjoint operation. */ - isAdjoint: boolean; - /** Control registers the gate acts on. */ - controls?: Register[]; - /** Target registers the gate acts on. */ - targets: Register[]; - /** Specify conditions on when to render operation. */ - conditionalRender?: ConditionalRender; - /** Custom data attributes to attach to gate element. */ - dataAttributes?: DataAttributes; + /** Gate label. */ + gate: string; + /** Formatted gate arguments to be displayed. */ + displayArgs?: string; + /** Nested operations within this operation. */ + children?: Operation[]; + /** Whether gate is a measurement operation. */ + isMeasurement: boolean; + /** Whether gate is a conditional operation. */ + isConditional: boolean; + /** Whether gate is a controlled operation. */ + isControlled: boolean; + /** Whether gate is an adjoint operation. */ + isAdjoint: boolean; + /** Control registers the gate acts on. */ + controls?: Register[]; + /** Target registers the gate acts on. */ + targets: Register[]; + /** Specify conditions on when to render operation. */ + conditionalRender?: ConditionalRender; + /** Custom data attributes to attach to gate element. */ + dataAttributes?: DataAttributes; } diff --git a/circuit_vis/src/constants.ts b/circuit_vis/src/constants.ts index 2ccb9e331f..fe2763319c 100644 --- a/circuit_vis/src/constants.ts +++ b/circuit_vis/src/constants.ts @@ -2,7 +2,7 @@ // Licensed under the MIT license. // SVG Namespace -export const svgNS = 'http://www.w3.org/2000/svg'; +export const svgNS = "http://www.w3.org/2000/svg"; // Display attributes /** Left padding of SVG. */ diff --git a/circuit_vis/src/formatters/formatUtils.ts b/circuit_vis/src/formatters/formatUtils.ts index 99b4ffa482..c3bccd1beb 100644 --- a/circuit_vis/src/formatters/formatUtils.ts +++ b/circuit_vis/src/formatters/formatUtils.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { labelFontSize, svgNS } from '../constants'; +import { labelFontSize, svgNS } from "../constants"; // Helper functions for basic SVG components @@ -13,10 +13,15 @@ import { labelFontSize, svgNS } from '../constants'; * * @returns SVG element. */ -export const createSvgElement = (type: string, attributes: { [attr: string]: string } = {}): SVGElement => { - const el: SVGElement = document.createElementNS(svgNS, type); - Object.entries(attributes).forEach(([attrName, attrVal]) => el.setAttribute(attrName, attrVal)); - return el; +export const createSvgElement = ( + type: string, + attributes: { [attr: string]: string } = {}, +): SVGElement => { + const el: SVGElement = document.createElementNS(svgNS, type); + Object.entries(attributes).forEach(([attrName, attrVal]) => + el.setAttribute(attrName, attrVal), + ); + return el; }; /** @@ -27,10 +32,13 @@ export const createSvgElement = (type: string, attributes: { [attr: string]: str * * @returns SVG element for grouped elements. */ -export const group = (svgElems: SVGElement[], attributes: { [attr: string]: string } = {}): SVGElement => { - const el: SVGElement = createSvgElement('g', attributes); - svgElems.forEach((child: SVGElement) => el.appendChild(child)); - return el; +export const group = ( + svgElems: SVGElement[], + attributes: { [attr: string]: string } = {}, +): SVGElement => { + const el: SVGElement = createSvgElement("g", attributes); + svgElems.forEach((child: SVGElement) => el.appendChild(child)); + return el; }; /** @@ -44,15 +52,21 @@ export const group = (svgElems: SVGElement[], attributes: { [attr: string]: stri * * @returns SVG element for line. */ -export const line = (x1: number, y1: number, x2: number, y2: number, className?: string): SVGElement => { - const attrs: { [attr: string]: string } = { - x1: x1.toString(), - x2: x2.toString(), - y1: y1.toString(), - y2: y2.toString(), - }; - if (className != null) attrs['class'] = className; - return createSvgElement('line', attrs); +export const line = ( + x1: number, + y1: number, + x2: number, + y2: number, + className?: string, +): SVGElement => { + const attrs: { [attr: string]: string } = { + x1: x1.toString(), + x2: x2.toString(), + y1: y1.toString(), + y2: y2.toString(), + }; + if (className != null) attrs["class"] = className; + return createSvgElement("line", attrs); }; /** @@ -64,14 +78,19 @@ export const line = (x1: number, y1: number, x2: number, y2: number, className?: * * @returns SVG element for circle. */ -export const circle = (x: number, y: number, radius: number, className?: string): SVGElement => { - const attrs: { [attr: string]: string } = { - cx: x.toString(), - cy: y.toString(), - r: radius.toString(), - }; - if (className != null) attrs['class'] = className; - return createSvgElement('circle', attrs); +export const circle = ( + x: number, + y: number, + radius: number, + className?: string, +): SVGElement => { + const attrs: { [attr: string]: string } = { + cx: x.toString(), + cy: y.toString(), + r: radius.toString(), + }; + if (className != null) attrs["class"] = className; + return createSvgElement("circle", attrs); }; /** @@ -83,7 +102,8 @@ export const circle = (x: number, y: number, radius: number, className?: string) * * @returns SVG element for control dot. */ -export const controlDot = (x: number, y: number, radius = 5): SVGElement => circle(x, y, radius, 'control-dot'); +export const controlDot = (x: number, y: number, radius = 5): SVGElement => + circle(x, y, radius, "control-dot"); /** * Generate the SVG representation of a unitary box that represents an arbitrary unitary operation. @@ -96,14 +116,20 @@ export const controlDot = (x: number, y: number, radius = 5): SVGElement => circ * * @returns SVG element for unitary box. */ -export const box = (x: number, y: number, width: number, height: number, className = 'gate-unitary'): SVGElement => - createSvgElement('rect', { - class: className, - x: x.toString(), - y: y.toString(), - width: width.toString(), - height: height.toString(), - }); +export const box = ( + x: number, + y: number, + width: number, + height: number, + className = "gate-unitary", +): SVGElement => + createSvgElement("rect", { + class: className, + x: x.toString(), + y: y.toString(), + width: width.toString(), + height: height.toString(), + }); /** * Generate the SVG text element from a given text string. @@ -115,14 +141,19 @@ export const box = (x: number, y: number, width: number, height: number, classNa * * @returns SVG element for text. */ -export const text = (text: string, x: number, y: number, fs: number = labelFontSize): SVGElement => { - const el: SVGElement = createSvgElement('text', { - 'font-size': fs.toString(), - x: x.toString(), - y: y.toString(), - }); - el.textContent = text; - return el; +export const text = ( + text: string, + x: number, + y: number, + fs: number = labelFontSize, +): SVGElement => { + const el: SVGElement = createSvgElement("text", { + "font-size": fs.toString(), + x: x.toString(), + y: y.toString(), + }); + el.textContent = text; + return el; }; /** @@ -136,10 +167,10 @@ export const text = (text: string, x: number, y: number, fs: number = labelFontS * @returns SVG element for arc. */ export const arc = (x: number, y: number, rx: number, ry: number): SVGElement => - createSvgElement('path', { - class: 'arc-measure', - d: `M ${x + 2 * rx} ${y} A ${rx} ${ry} 0 0 0 ${x} ${y}`, - }); + createSvgElement("path", { + class: "arc-measure", + d: `M ${x + 2 * rx} ${y} A ${rx} ${ry} 0 0 0 ${x} ${y}`, + }); /** * Generate a dashed SVG line. @@ -152,10 +183,16 @@ export const arc = (x: number, y: number, rx: number, ry: number): SVGElement => * * @returns SVG element for dashed line. */ -export const dashedLine = (x1: number, y1: number, x2: number, y2: number, className?: string): SVGElement => { - const el: SVGElement = line(x1, y1, x2, y2, className); - el.setAttribute('stroke-dasharray', '8, 8'); - return el; +export const dashedLine = ( + x1: number, + y1: number, + x2: number, + y2: number, + className?: string, +): SVGElement => { + const el: SVGElement = line(x1, y1, x2, y2, className); + el.setAttribute("stroke-dasharray", "8, 8"); + return el; }; /** @@ -169,9 +206,15 @@ export const dashedLine = (x1: number, y1: number, x2: number, y2: number, class * * @returns SVG element for dashed box. */ -export const dashedBox = (x: number, y: number, width: number, height: number, className?: string): SVGElement => { - const el: SVGElement = box(x, y, width, height, className); - el.setAttribute('fill-opacity', '0'); - el.setAttribute('stroke-dasharray', '8, 8'); - return el; +export const dashedBox = ( + x: number, + y: number, + width: number, + height: number, + className?: string, +): SVGElement => { + const el: SVGElement = box(x, y, width, height, className); + el.setAttribute("fill-opacity", "0"); + el.setAttribute("stroke-dasharray", "8, 8"); + return el; }; diff --git a/circuit_vis/src/formatters/gateFormatter.ts b/circuit_vis/src/formatters/gateFormatter.ts index 16588ff3d4..fda0932623 100644 --- a/circuit_vis/src/formatters/gateFormatter.ts +++ b/circuit_vis/src/formatters/gateFormatter.ts @@ -1,30 +1,30 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { Metadata, GateType } from '../metadata'; +import { Metadata, GateType } from "../metadata"; import { - minGateWidth, - gateHeight, - labelFontSize, - argsFontSize, - controlBtnRadius, - controlBtnOffset, - groupBoxPadding, - classicalRegHeight, - nestedGroupPadding, -} from '../constants'; + minGateWidth, + gateHeight, + labelFontSize, + argsFontSize, + controlBtnRadius, + controlBtnOffset, + groupBoxPadding, + classicalRegHeight, + nestedGroupPadding, +} from "../constants"; import { - createSvgElement, - group, - line, - circle, - controlDot, - box, - text, - arc, - dashedLine, - dashedBox, -} from './formatUtils'; + createSvgElement, + group, + line, + circle, + controlDot, + box, + text, + arc, + dashedLine, + dashedBox, +} from "./formatUtils"; /** * Given an array of operations (in metadata format), return the SVG representation. @@ -35,8 +35,10 @@ import { * @returns SVG representation of operations. */ const formatGates = (opsMetadata: Metadata[], nestedDepth = 0): SVGElement => { - const formattedGates: SVGElement[] = opsMetadata.map((metadata) => _formatGate(metadata, nestedDepth)); - return group(formattedGates); + const formattedGates: SVGElement[] = opsMetadata.map((metadata) => + _formatGate(metadata, nestedDepth), + ); + return group(formattedGates); }; /** @@ -48,28 +50,32 @@ const formatGates = (opsMetadata: Metadata[], nestedDepth = 0): SVGElement => { * @returns SVG representation of gate. */ const _formatGate = (metadata: Metadata, nestedDepth = 0): SVGElement => { - const { type, x, controlsY, targetsY, label, displayArgs, width } = metadata; - switch (type) { - case GateType.Measure: - return _createGate([_measure(x, controlsY[0])], metadata, nestedDepth); - case GateType.Unitary: - return _createGate([_unitary(label, x, targetsY as number[][], width, displayArgs)], metadata, nestedDepth); - case GateType.X: - return _createGate([_x(metadata, nestedDepth)], metadata, nestedDepth); - case GateType.Swap: - return controlsY.length > 0 - ? _controlledGate(metadata, nestedDepth) - : _createGate([_swap(metadata, nestedDepth)], metadata, nestedDepth); - case GateType.Cnot: - case GateType.ControlledUnitary: - return _controlledGate(metadata, nestedDepth); - case GateType.Group: - return _groupedOperations(metadata, nestedDepth); - case GateType.ClassicalControlled: - return _classicalControlled(metadata); - default: - throw new Error(`ERROR: unknown gate (${label}) of type ${type}.`); - } + const { type, x, controlsY, targetsY, label, displayArgs, width } = metadata; + switch (type) { + case GateType.Measure: + return _createGate([_measure(x, controlsY[0])], metadata, nestedDepth); + case GateType.Unitary: + return _createGate( + [_unitary(label, x, targetsY as number[][], width, displayArgs)], + metadata, + nestedDepth, + ); + case GateType.X: + return _createGate([_x(metadata, nestedDepth)], metadata, nestedDepth); + case GateType.Swap: + return controlsY.length > 0 + ? _controlledGate(metadata, nestedDepth) + : _createGate([_swap(metadata, nestedDepth)], metadata, nestedDepth); + case GateType.Cnot: + case GateType.ControlledUnitary: + return _controlledGate(metadata, nestedDepth); + case GateType.Group: + return _groupedOperations(metadata, nestedDepth); + case GateType.ClassicalControlled: + return _classicalControlled(metadata); + default: + throw new Error(`ERROR: unknown gate (${label}) of type ${type}.`); + } }; /** @@ -80,14 +86,20 @@ const _formatGate = (metadata: Metadata, nestedDepth = 0): SVGElement => { * * @returns SVG representation of a gate. */ -const _createGate = (svgElems: SVGElement[], metadata: Metadata, nestedDepth: number): SVGElement => { - const { dataAttributes } = metadata || {}; - const attributes: { [attr: string]: string } = { class: 'gate' }; - Object.entries(dataAttributes || {}).forEach(([attr, val]) => (attributes[`data-${attr}`] = val)); - - const zoomBtn: SVGElement | null = _zoomButton(metadata, nestedDepth); - if (zoomBtn != null) svgElems = svgElems.concat([zoomBtn]); - return group(svgElems, attributes); +const _createGate = ( + svgElems: SVGElement[], + metadata: Metadata, + nestedDepth: number, +): SVGElement => { + const { dataAttributes } = metadata || {}; + const attributes: { [attr: string]: string } = { class: "gate" }; + Object.entries(dataAttributes || {}).forEach( + ([attr, val]) => (attributes[`data-${attr}`] = val), + ); + + const zoomBtn: SVGElement | null = _zoomButton(metadata, nestedDepth); + if (zoomBtn != null) svgElems = svgElems.concat([zoomBtn]); + return group(svgElems, attributes); }; /** @@ -99,32 +111,39 @@ const _createGate = (svgElems: SVGElement[], metadata: Metadata, nestedDepth: nu * * @returns SVG element for expand/collapse button if needed, or null otherwise. */ -const _zoomButton = (metadata: Metadata, nestedDepth: number): SVGElement | null => { - if (metadata == undefined) return null; - - const [x1, y1] = _gatePosition(metadata, nestedDepth); - let { dataAttributes } = metadata; - dataAttributes = dataAttributes || {}; - - const expanded = 'expanded' in dataAttributes; - - const x = x1 + 2; - const y = y1 + 2; - const circleBorder: SVGElement = circle(x, y, 10); - - if (expanded) { - // Create collapse button if expanded - const minusSign: SVGElement = createSvgElement('path', { d: `M${x - 7},${y} h14` }); - const elements: SVGElement[] = [circleBorder, minusSign]; - return group(elements, { class: 'gate-control gate-collapse' }); - } else if (dataAttributes['zoom-in'] == 'true') { - // Create expand button if operation can be zoomed in - const plusSign: SVGElement = createSvgElement('path', { d: `M${x},${y - 7} v14 M${x - 7},${y} h14` }); - const elements: SVGElement[] = [circleBorder, plusSign]; - return group(elements, { class: 'gate-control gate-expand' }); - } - - return null; +const _zoomButton = ( + metadata: Metadata, + nestedDepth: number, +): SVGElement | null => { + if (metadata == undefined) return null; + + const [x1, y1] = _gatePosition(metadata, nestedDepth); + let { dataAttributes } = metadata; + dataAttributes = dataAttributes || {}; + + const expanded = "expanded" in dataAttributes; + + const x = x1 + 2; + const y = y1 + 2; + const circleBorder: SVGElement = circle(x, y, 10); + + if (expanded) { + // Create collapse button if expanded + const minusSign: SVGElement = createSvgElement("path", { + d: `M${x - 7},${y} h14`, + }); + const elements: SVGElement[] = [circleBorder, minusSign]; + return group(elements, { class: "gate-control gate-collapse" }); + } else if (dataAttributes["zoom-in"] == "true") { + // Create expand button if operation can be zoomed in + const plusSign: SVGElement = createSvgElement("path", { + d: `M${x},${y - 7} v14 M${x - 7},${y} h14`, + }); + const elements: SVGElement[] = [circleBorder, plusSign]; + return group(elements, { class: "gate-control gate-expand" }); + } + + return null; }; /** @@ -135,34 +154,37 @@ const _zoomButton = (metadata: Metadata, nestedDepth: number): SVGElement | null * * @returns Coordinates of gate: [x1, y1, x2, y2]. */ -const _gatePosition = (metadata: Metadata, nestedDepth: number): [number, number, number, number] => { - const { x, width, type, targetsY } = metadata; +const _gatePosition = ( + metadata: Metadata, + nestedDepth: number, +): [number, number, number, number] => { + const { x, width, type, targetsY } = metadata; - const ys = targetsY?.flatMap((y) => y as number[]) || []; - const maxY = Math.max(...ys); - const minY = Math.min(...ys); + const ys = targetsY?.flatMap((y) => y as number[]) || []; + const maxY = Math.max(...ys); + const minY = Math.min(...ys); - let x1: number, y1: number, x2: number, y2: number; + let x1: number, y1: number, x2: number, y2: number; - switch (type) { - case GateType.Group: - const padding = groupBoxPadding - nestedDepth * nestedGroupPadding; + switch (type) { + case GateType.Group: + const padding = groupBoxPadding - nestedDepth * nestedGroupPadding; - x1 = x - 2 * padding; - y1 = minY - gateHeight / 2 - padding; - x2 = width + 2 * padding; - y2 = maxY + +gateHeight / 2 + padding - (minY - gateHeight / 2 - padding); + x1 = x - 2 * padding; + y1 = minY - gateHeight / 2 - padding; + x2 = width + 2 * padding; + y2 = maxY + +gateHeight / 2 + padding - (minY - gateHeight / 2 - padding); - return [x1, y1, x2, y2]; + return [x1, y1, x2, y2]; - default: - x1 = x - width / 2; - y1 = minY - gateHeight / 2; - x2 = x + width; - y2 = maxY + gateHeight / 2; - } + default: + x1 = x - width / 2; + y1 = minY - gateHeight / 2; + x2 = x + width; + y2 = maxY + gateHeight / 2; + } - return [x1, y1, x2, y2]; + return [x1, y1, x2, y2]; }; /** @@ -174,14 +196,25 @@ const _gatePosition = (metadata: Metadata, nestedDepth: number): [number, number * @returns SVG representation of measurement gate. */ const _measure = (x: number, y: number): SVGElement => { - x -= minGateWidth / 2; - const width: number = minGateWidth, - height = gateHeight; - // Draw measurement box - const mBox: SVGElement = box(x, y - height / 2, width, height, 'gate-measure'); - const mArc: SVGElement = arc(x + 5, y + 2, width / 2 - 5, height / 2 - 8); - const meter: SVGElement = line(x + width / 2, y + 8, x + width - 8, y - height / 2 + 8); - return group([mBox, mArc, meter]); + x -= minGateWidth / 2; + const width: number = minGateWidth, + height = gateHeight; + // Draw measurement box + const mBox: SVGElement = box( + x, + y - height / 2, + width, + height, + "gate-measure", + ); + const mArc: SVGElement = arc(x + 5, y + 2, width / 2 - 5, height / 2 - 8); + const meter: SVGElement = line( + x + width / 2, + y + 8, + x + width - 8, + y - height / 2 + 8, + ); + return group([mBox, mArc, meter]); }; /** @@ -197,34 +230,37 @@ const _measure = (x: number, y: number): SVGElement => { * @returns SVG representation of unitary gate. */ const _unitary = ( - label: string, - x: number, - y: number[][], - width: number, - displayArgs?: string, - renderDashedLine = true, + label: string, + x: number, + y: number[][], + width: number, + displayArgs?: string, + renderDashedLine = true, ): SVGElement => { - if (y.length === 0) throw new Error(`Failed to render unitary gate (${label}): has no y-values`); - - // Render each group as a separate unitary boxes - const unitaryBoxes: SVGElement[] = y.map((group: number[]) => { - const maxY: number = group[group.length - 1], - minY: number = group[0]; - const height: number = maxY - minY + gateHeight; - return _unitaryBox(label, x, minY, width, height, displayArgs); - }); - - // Draw dashed line between disconnected unitaries - if (renderDashedLine && unitaryBoxes.length > 1) { - const lastBox: number[] = y[y.length - 1]; - const firstBox: number[] = y[0]; - const maxY: number = lastBox[lastBox.length - 1], - minY: number = firstBox[0]; - const vertLine: SVGElement = dashedLine(x, minY, x, maxY); - return group([vertLine, ...unitaryBoxes]); - } - - return group(unitaryBoxes); + if (y.length === 0) + throw new Error( + `Failed to render unitary gate (${label}): has no y-values`, + ); + + // Render each group as a separate unitary boxes + const unitaryBoxes: SVGElement[] = y.map((group: number[]) => { + const maxY: number = group[group.length - 1], + minY: number = group[0]; + const height: number = maxY - minY + gateHeight; + return _unitaryBox(label, x, minY, width, height, displayArgs); + }); + + // Draw dashed line between disconnected unitaries + if (renderDashedLine && unitaryBoxes.length > 1) { + const lastBox: number[] = y[y.length - 1]; + const firstBox: number[] = y[0]; + const maxY: number = lastBox[lastBox.length - 1], + minY: number = firstBox[0]; + const vertLine: SVGElement = dashedLine(x, minY, x, maxY); + return group([vertLine, ...unitaryBoxes]); + } + + return group(unitaryBoxes); }; /** @@ -240,24 +276,24 @@ const _unitary = ( * @returns SVG representation of unitary box. */ const _unitaryBox = ( - label: string, - x: number, - y: number, - width: number, - height: number = gateHeight, - displayArgs?: string, + label: string, + x: number, + y: number, + width: number, + height: number = gateHeight, + displayArgs?: string, ): SVGElement => { - y -= gateHeight / 2; - const uBox: SVGElement = box(x - width / 2, y, width, height); - const labelY = y + height / 2 - (displayArgs == null ? 0 : 7); - const labelText: SVGElement = text(label, x, labelY); - const elems = [uBox, labelText]; - if (displayArgs != null) { - const argStrY = y + height / 2 + 8; - const argText: SVGElement = text(displayArgs, x, argStrY, argsFontSize); - elems.push(argText); - } - return group(elems); + y -= gateHeight / 2; + const uBox: SVGElement = box(x - width / 2, y, width, height); + const labelY = y + height / 2 - (displayArgs == null ? 0 : 7); + const labelText: SVGElement = text(label, x, labelY); + const elems = [uBox, labelText]; + if (displayArgs != null) { + const argStrY = y + height / 2 + 8; + const argText: SVGElement = text(displayArgs, x, argStrY, argsFontSize); + elems.push(argText); + } + return group(elems); }; /** @@ -269,16 +305,16 @@ const _unitaryBox = ( * @returns SVG representation of SWAP gate. */ const _swap = (metadata: Metadata, nestedDepth: number): SVGElement => { - const { x, targetsY } = metadata; + const { x, targetsY } = metadata; - // Get SVGs of crosses - const [x1, y1, x2, y2] = _gatePosition(metadata, nestedDepth); - const ys = targetsY?.flatMap((y) => y as number[]) || []; + // Get SVGs of crosses + const [x1, y1, x2, y2] = _gatePosition(metadata, nestedDepth); + const ys = targetsY?.flatMap((y) => y as number[]) || []; - const bg: SVGElement = box(x1, y1, x2, y2, 'gate-swap'); - const crosses: SVGElement[] = ys.map((y) => _cross(x, y)); - const vertLine: SVGElement = line(x, ys[0], x, ys[1]); - return group([bg, ...crosses, vertLine]); + const bg: SVGElement = box(x1, y1, x2, y2, "gate-swap"); + const crosses: SVGElement[] = ys.map((y) => _cross(x, y)); + const vertLine: SVGElement = line(x, ys[0], x, ys[1]); + return group([bg, ...crosses, vertLine]); }; /** * Creates the SVG for an X gate @@ -286,9 +322,9 @@ const _swap = (metadata: Metadata, nestedDepth: number): SVGElement => { * @returns SVG representation of X gate. */ const _x = (metadata: Metadata, _: number): SVGElement => { - const { x, targetsY } = metadata; - const ys = targetsY.flatMap((y) => y as number[]); - return _oplus(x, ys[0]); + const { x, targetsY } = metadata; + const ys = targetsY.flatMap((y) => y as number[]); + return _oplus(x, ys[0]); }; /** * Generates cross for display in SWAP gate. @@ -299,10 +335,20 @@ const _x = (metadata: Metadata, _: number): SVGElement => { * @returns SVG representation for cross. */ const _cross = (x: number, y: number): SVGElement => { - const radius = 8; - const line1: SVGElement = line(x - radius, y - radius, x + radius, y + radius); - const line2: SVGElement = line(x - radius, y + radius, x + radius, y - radius); - return group([line1, line2]); + const radius = 8; + const line1: SVGElement = line( + x - radius, + y - radius, + x + radius, + y + radius, + ); + const line2: SVGElement = line( + x - radius, + y + radius, + x + radius, + y - radius, + ); + return group([line1, line2]); }; /** @@ -312,35 +358,46 @@ const _cross = (x: number, y: number): SVGElement => { * * @returns SVG representation of controlled gate. */ -const _controlledGate = (metadata: Metadata, nestedDepth: number): SVGElement => { - const targetGateSvgs: SVGElement[] = []; - const { type, x, controlsY, label, displayArgs, width } = metadata; - let { targetsY } = metadata; - - // Get SVG for target gates - switch (type) { - case GateType.Cnot: - (targetsY as number[]).forEach((y) => targetGateSvgs.push(_oplus(x, y))); - break; - case GateType.Swap: - (targetsY as number[]).forEach((y) => targetGateSvgs.push(_cross(x, y))); - break; - case GateType.ControlledUnitary: - const groupedTargetsY: number[][] = targetsY as number[][]; - targetGateSvgs.push(_unitary(label, x, groupedTargetsY, width, displayArgs, false)); - targetsY = targetsY.flat(); - break; - default: - throw new Error(`ERROR: Unrecognized gate: ${label} of type ${type}`); - } - // Get SVGs for control dots - const controlledDotsSvg: SVGElement[] = controlsY.map((y) => controlDot(x, y)); - // Create control lines - const maxY: number = Math.max(...controlsY, ...(targetsY as number[])); - const minY: number = Math.min(...controlsY, ...(targetsY as number[])); - const vertLine: SVGElement = line(x, minY, x, maxY); - const svg: SVGElement = _createGate([vertLine, ...controlledDotsSvg, ...targetGateSvgs], metadata, nestedDepth); - return svg; +const _controlledGate = ( + metadata: Metadata, + nestedDepth: number, +): SVGElement => { + const targetGateSvgs: SVGElement[] = []; + const { type, x, controlsY, label, displayArgs, width } = metadata; + let { targetsY } = metadata; + + // Get SVG for target gates + switch (type) { + case GateType.Cnot: + (targetsY as number[]).forEach((y) => targetGateSvgs.push(_oplus(x, y))); + break; + case GateType.Swap: + (targetsY as number[]).forEach((y) => targetGateSvgs.push(_cross(x, y))); + break; + case GateType.ControlledUnitary: + const groupedTargetsY: number[][] = targetsY as number[][]; + targetGateSvgs.push( + _unitary(label, x, groupedTargetsY, width, displayArgs, false), + ); + targetsY = targetsY.flat(); + break; + default: + throw new Error(`ERROR: Unrecognized gate: ${label} of type ${type}`); + } + // Get SVGs for control dots + const controlledDotsSvg: SVGElement[] = controlsY.map((y) => + controlDot(x, y), + ); + // Create control lines + const maxY: number = Math.max(...controlsY, ...(targetsY as number[])); + const minY: number = Math.min(...controlsY, ...(targetsY as number[])); + const vertLine: SVGElement = line(x, minY, x, maxY); + const svg: SVGElement = _createGate( + [vertLine, ...controlledDotsSvg, ...targetGateSvgs], + metadata, + nestedDepth, + ); + return svg; }; /** @@ -353,10 +410,10 @@ const _controlledGate = (metadata: Metadata, nestedDepth: number): SVGElement => * @returns SVG representation of $\oplus$ symbol. */ const _oplus = (x: number, y: number, r = 15): SVGElement => { - const circleBorder: SVGElement = circle(x, y, r); - const vertLine: SVGElement = line(x, y - r, x, y + r); - const horLine: SVGElement = line(x - r, y, x + r, y); - return group([circleBorder, vertLine, horLine], { class: 'oplus' }); + const circleBorder: SVGElement = circle(x, y, r); + const vertLine: SVGElement = line(x, y - r, x, y + r); + const horLine: SVGElement = line(x - r, y, x + r, y); + return group([circleBorder, vertLine, horLine], { class: "oplus" }); }; /** @@ -367,15 +424,19 @@ const _oplus = (x: number, y: number, r = 15): SVGElement => { * * @returns SVG representation of gate. */ -const _groupedOperations = (metadata: Metadata, nestedDepth: number): SVGElement => { - const { children } = metadata; - const [x1, y1, x2, y2] = _gatePosition(metadata, nestedDepth); - - // Draw dashed box around children gates - const box: SVGElement = dashedBox(x1, y1, x2, y2); - const elems: SVGElement[] = [box]; - if (children != null) elems.push(formatGates(children as Metadata[], nestedDepth + 1)); - return _createGate(elems, metadata, nestedDepth); +const _groupedOperations = ( + metadata: Metadata, + nestedDepth: number, +): SVGElement => { + const { children } = metadata; + const [x1, y1, x2, y2] = _gatePosition(metadata, nestedDepth); + + // Draw dashed box around children gates + const box: SVGElement = dashedBox(x1, y1, x2, y2); + const elems: SVGElement[] = [box]; + if (children != null) + elems.push(formatGates(children as Metadata[], nestedDepth + 1)); + return _createGate(elems, metadata, nestedDepth); }; /** @@ -386,58 +447,77 @@ const _groupedOperations = (metadata: Metadata, nestedDepth: number): SVGElement * * @returns SVG representation of gate. */ -const _classicalControlled = (metadata: Metadata, padding: number = groupBoxPadding): SVGElement => { - const { controlsY, dataAttributes } = metadata; - const targetsY: number[] = metadata.targetsY as number[]; - const children: Metadata[][] = metadata.children as Metadata[][]; - let { x, width } = metadata; - - const controlY = controlsY[0]; - - const elems: SVGElement[] = []; - - if (children != null) { - if (children.length !== 2) - throw new Error(`Invalid number of children found for classically-controlled gate: ${children.length}`); - - // Get SVG for gates controlled on 0 - const childrenZero: SVGElement = formatGates(children[0]); - childrenZero.setAttribute('class', 'gates-zero'); - elems.push(childrenZero); - - // Get SVG for gates controlled on 1 - const childrenOne: SVGElement = formatGates(children[1]); - childrenOne.setAttribute('class', 'gates-one'); - elems.push(childrenOne); - } - - // Draw control button and attached dashed line to dashed box - const controlCircleX: number = x + controlBtnRadius; - const controlCircle: SVGElement = _controlCircle(controlCircleX, controlY); - const lineY1: number = controlY + controlBtnRadius, - lineY2: number = controlY + classicalRegHeight / 2; - const vertLine: SVGElement = dashedLine(controlCircleX, lineY1, controlCircleX, lineY2, 'classical-line'); - x += controlBtnOffset; - const horLine: SVGElement = dashedLine(controlCircleX, lineY2, x, lineY2, 'classical-line'); - - width = width - controlBtnOffset + (padding - groupBoxPadding) * 2; - x += groupBoxPadding - padding; - const y: number = targetsY[0] - gateHeight / 2 - padding; - const height: number = targetsY[1] - targetsY[0] + gateHeight + padding * 2; - - // Draw dashed box around children gates - const box: SVGElement = dashedBox(x, y, width, height, 'classical-container'); - - elems.push(...[horLine, vertLine, controlCircle, box]); - - // Display controlled operation in initial "unknown" state - const attributes: { [attr: string]: string } = { - class: `classically-controlled-group classically-controlled-unknown`, - }; - if (dataAttributes != null) - Object.entries(dataAttributes).forEach(([attr, val]) => (attributes[`data-${attr}`] = val)); - - return group(elems, attributes); +const _classicalControlled = ( + metadata: Metadata, + padding: number = groupBoxPadding, +): SVGElement => { + const { controlsY, dataAttributes } = metadata; + const targetsY: number[] = metadata.targetsY as number[]; + const children: Metadata[][] = metadata.children as Metadata[][]; + let { x, width } = metadata; + + const controlY = controlsY[0]; + + const elems: SVGElement[] = []; + + if (children != null) { + if (children.length !== 2) + throw new Error( + `Invalid number of children found for classically-controlled gate: ${children.length}`, + ); + + // Get SVG for gates controlled on 0 + const childrenZero: SVGElement = formatGates(children[0]); + childrenZero.setAttribute("class", "gates-zero"); + elems.push(childrenZero); + + // Get SVG for gates controlled on 1 + const childrenOne: SVGElement = formatGates(children[1]); + childrenOne.setAttribute("class", "gates-one"); + elems.push(childrenOne); + } + + // Draw control button and attached dashed line to dashed box + const controlCircleX: number = x + controlBtnRadius; + const controlCircle: SVGElement = _controlCircle(controlCircleX, controlY); + const lineY1: number = controlY + controlBtnRadius, + lineY2: number = controlY + classicalRegHeight / 2; + const vertLine: SVGElement = dashedLine( + controlCircleX, + lineY1, + controlCircleX, + lineY2, + "classical-line", + ); + x += controlBtnOffset; + const horLine: SVGElement = dashedLine( + controlCircleX, + lineY2, + x, + lineY2, + "classical-line", + ); + + width = width - controlBtnOffset + (padding - groupBoxPadding) * 2; + x += groupBoxPadding - padding; + const y: number = targetsY[0] - gateHeight / 2 - padding; + const height: number = targetsY[1] - targetsY[0] + gateHeight + padding * 2; + + // Draw dashed box around children gates + const box: SVGElement = dashedBox(x, y, width, height, "classical-container"); + + elems.push(...[horLine, vertLine, controlCircle, box]); + + // Display controlled operation in initial "unknown" state + const attributes: { [attr: string]: string } = { + class: `classically-controlled-group classically-controlled-unknown`, + }; + if (dataAttributes != null) + Object.entries(dataAttributes).forEach( + ([attr, val]) => (attributes[`data-${attr}`] = val), + ); + + return group(elems, attributes); }; /** @@ -450,18 +530,24 @@ const _classicalControlled = (metadata: Metadata, padding: number = groupBoxPadd * * @returns SVG representation of control circle. */ -const _controlCircle = (x: number, y: number, r: number = controlBtnRadius): SVGElement => - group([circle(x, y, r), text('?', x, y, labelFontSize)], { class: 'classically-controlled-btn' }); +const _controlCircle = ( + x: number, + y: number, + r: number = controlBtnRadius, +): SVGElement => + group([circle(x, y, r), text("?", x, y, labelFontSize)], { + class: "classically-controlled-btn", + }); export { - formatGates, - _formatGate, - _createGate, - _zoomButton, - _measure, - _unitary, - _swap, - _controlledGate, - _groupedOperations, - _classicalControlled, + formatGates, + _formatGate, + _createGate, + _zoomButton, + _measure, + _unitary, + _swap, + _controlledGate, + _groupedOperations, + _classicalControlled, }; diff --git a/circuit_vis/src/formatters/inputFormatter.ts b/circuit_vis/src/formatters/inputFormatter.ts index e3acf98228..7464de4c33 100644 --- a/circuit_vis/src/formatters/inputFormatter.ts +++ b/circuit_vis/src/formatters/inputFormatter.ts @@ -1,10 +1,15 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { Qubit } from '../circuit'; -import { RegisterType, RegisterMap, RegisterMetadata } from '../register'; -import { leftPadding, startY, registerHeight, classicalRegHeight } from '../constants'; -import { group, text } from './formatUtils'; +import { Qubit } from "../circuit"; +import { RegisterType, RegisterMap, RegisterMetadata } from "../register"; +import { + leftPadding, + startY, + registerHeight, + classicalRegHeight, +} from "../constants"; +import { group, text } from "./formatUtils"; /** * `formatInputs` takes in an array of Qubits and outputs the SVG string of formatted @@ -15,40 +20,45 @@ import { group, text } from './formatUtils'; * @returns returns the SVG string of formatted qubit wires, a mapping from registers * to y coord and total SVG height. */ -const formatInputs = (qubits: Qubit[]): { qubitWires: SVGElement; registers: RegisterMap; svgHeight: number } => { - const qubitWires: SVGElement[] = []; - const registers: RegisterMap = {}; +const formatInputs = ( + qubits: Qubit[], +): { qubitWires: SVGElement; registers: RegisterMap; svgHeight: number } => { + const qubitWires: SVGElement[] = []; + const registers: RegisterMap = {}; - let currY: number = startY; - qubits.forEach(({ id, numChildren }) => { - // Add qubit wire to list of qubit wires - qubitWires.push(_qubitInput(currY)); + let currY: number = startY; + qubits.forEach(({ id, numChildren }) => { + // Add qubit wire to list of qubit wires + qubitWires.push(_qubitInput(currY)); - // Create qubit register - registers[id] = { type: RegisterType.Qubit, y: currY }; + // Create qubit register + registers[id] = { type: RegisterType.Qubit, y: currY }; - // If there are no attached classical registers, increment y by fixed register height - if (numChildren == null || numChildren === 0) { - currY += registerHeight; - return; - } + // If there are no attached classical registers, increment y by fixed register height + if (numChildren == null || numChildren === 0) { + currY += registerHeight; + return; + } - // Increment current height by classical register height for attached classical registers - currY += classicalRegHeight; + // Increment current height by classical register height for attached classical registers + currY += classicalRegHeight; - // Add classical wires - registers[id].children = Array.from(Array(numChildren), () => { - const clsReg: RegisterMetadata = { type: RegisterType.Classical, y: currY }; - currY += classicalRegHeight; - return clsReg; - }); + // Add classical wires + registers[id].children = Array.from(Array(numChildren), () => { + const clsReg: RegisterMetadata = { + type: RegisterType.Classical, + y: currY, + }; + currY += classicalRegHeight; + return clsReg; }); + }); - return { - qubitWires: group(qubitWires), - registers, - svgHeight: currY, - }; + return { + qubitWires: group(qubitWires), + registers, + svgHeight: currY, + }; }; /** @@ -59,10 +69,10 @@ const formatInputs = (qubits: Qubit[]): { qubitWires: SVGElement; registers: Reg * @returns SVG text component for the input register. */ const _qubitInput = (y: number): SVGElement => { - const el: SVGElement = text('|0⟩', leftPadding, y, 16); - el.setAttribute('text-anchor', 'start'); - el.setAttribute('dominant-baseline', 'middle'); - return el; + const el: SVGElement = text("|0⟩", leftPadding, y, 16); + el.setAttribute("text-anchor", "start"); + el.setAttribute("dominant-baseline", "middle"); + return el; }; export { formatInputs, _qubitInput }; diff --git a/circuit_vis/src/formatters/registerFormatter.ts b/circuit_vis/src/formatters/registerFormatter.ts index 3d9637c903..aa858e9278 100644 --- a/circuit_vis/src/formatters/registerFormatter.ts +++ b/circuit_vis/src/formatters/registerFormatter.ts @@ -1,10 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { RegisterMap } from '../register'; -import { regLineStart } from '../constants'; -import { Metadata, GateType } from '../metadata'; -import { group, line, text } from './formatUtils'; +import { RegisterMap } from "../register"; +import { regLineStart } from "../constants"; +import { Metadata, GateType } from "../metadata"; +import { group, line, text } from "./formatUtils"; /** * Generate the SVG representation of the qubit register wires in `registers` and the classical wires @@ -16,21 +16,25 @@ import { group, line, text } from './formatUtils'; * * @returns SVG representation of register wires. */ -const formatRegisters = (registers: RegisterMap, measureGates: Metadata[], endX: number): SVGElement => { - const formattedRegs: SVGElement[] = []; - // Render qubit wires - for (const qId in registers) { - formattedRegs.push(_qubitRegister(Number(qId), endX, registers[qId].y)); - } - // Render classical wires - measureGates.forEach(({ type, x, targetsY, controlsY }) => { - if (type !== GateType.Measure) return; - const gateY: number = controlsY[0]; - (targetsY as number[]).forEach((y) => { - formattedRegs.push(_classicalRegister(x, gateY, endX, y)); - }); +const formatRegisters = ( + registers: RegisterMap, + measureGates: Metadata[], + endX: number, +): SVGElement => { + const formattedRegs: SVGElement[] = []; + // Render qubit wires + for (const qId in registers) { + formattedRegs.push(_qubitRegister(Number(qId), endX, registers[qId].y)); + } + // Render classical wires + measureGates.forEach(({ type, x, targetsY, controlsY }) => { + if (type !== GateType.Measure) return; + const gateY: number = controlsY[0]; + (targetsY as number[]).forEach((y) => { + formattedRegs.push(_classicalRegister(x, gateY, endX, y)); }); - return group(formattedRegs); + }); + return group(formattedRegs); }; /** @@ -43,41 +47,46 @@ const formatRegisters = (registers: RegisterMap, measureGates: Metadata[], endX: * * @returns SVG representation of the given classical register. */ -const _classicalRegister = (startX: number, gateY: number, endX: number, wireY: number): SVGElement => { - const wirePadding = 1; - // Draw vertical lines - const vLine1: SVGElement = line( - startX + wirePadding, - gateY, - startX + wirePadding, - wireY - wirePadding, - 'register-classical', - ); - const vLine2: SVGElement = line( - startX - wirePadding, - gateY, - startX - wirePadding, - wireY + wirePadding, - 'register-classical', - ); +const _classicalRegister = ( + startX: number, + gateY: number, + endX: number, + wireY: number, +): SVGElement => { + const wirePadding = 1; + // Draw vertical lines + const vLine1: SVGElement = line( + startX + wirePadding, + gateY, + startX + wirePadding, + wireY - wirePadding, + "register-classical", + ); + const vLine2: SVGElement = line( + startX - wirePadding, + gateY, + startX - wirePadding, + wireY + wirePadding, + "register-classical", + ); - // Draw horizontal lines - const hLine1: SVGElement = line( - startX + wirePadding, - wireY - wirePadding, - endX, - wireY - wirePadding, - 'register-classical', - ); - const hLine2: SVGElement = line( - startX - wirePadding, - wireY + wirePadding, - endX, - wireY + wirePadding, - 'register-classical', - ); + // Draw horizontal lines + const hLine1: SVGElement = line( + startX + wirePadding, + wireY - wirePadding, + endX, + wireY - wirePadding, + "register-classical", + ); + const hLine2: SVGElement = line( + startX - wirePadding, + wireY + wirePadding, + endX, + wireY + wirePadding, + "register-classical", + ); - return group([vLine1, vLine2, hLine1, hLine2]); + return group([vLine1, vLine2, hLine1, hLine2]); }; /** @@ -90,15 +99,20 @@ const _classicalRegister = (startX: number, gateY: number, endX: number, wireY: * * @returns SVG representation of the given qubit register. */ -const _qubitRegister = (qId: number, endX: number, y: number, labelOffset = 16): SVGElement => { - const wire: SVGElement = line(regLineStart, y, endX, y); +const _qubitRegister = ( + qId: number, + endX: number, + y: number, + labelOffset = 16, +): SVGElement => { + const wire: SVGElement = line(regLineStart, y, endX, y); - const label: SVGElement = text(`q${qId}`, regLineStart, y - labelOffset); - label.setAttribute('dominant-baseline', 'hanging'); - label.setAttribute('text-anchor', 'start'); - label.setAttribute('font-size', '75%'); + const label: SVGElement = text(`q${qId}`, regLineStart, y - labelOffset); + label.setAttribute("dominant-baseline", "hanging"); + label.setAttribute("text-anchor", "start"); + label.setAttribute("font-size", "75%"); - return group([wire, label]); + return group([wire, label]); }; export { formatRegisters, _classicalRegister, _qubitRegister }; diff --git a/circuit_vis/src/index.ts b/circuit_vis/src/index.ts index 0a0402686c..5e37c199f8 100644 --- a/circuit_vis/src/index.ts +++ b/circuit_vis/src/index.ts @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { Sqore } from './sqore'; -import { Circuit } from './circuit'; -import { StyleConfig } from './styles'; +import { Sqore } from "./sqore"; +import { Circuit } from "./circuit"; +import { StyleConfig } from "./styles"; /** * Render `circuit` into `container` at the specified layer depth. @@ -14,17 +14,17 @@ import { StyleConfig } from './styles'; * @param renderDepth Initial layer depth at which to render gates. */ export const draw = ( - circuit: Circuit, - container: HTMLElement, - style: StyleConfig | string = {}, - renderDepth = 0, + circuit: Circuit, + container: HTMLElement, + style: StyleConfig | string = {}, + renderDepth = 0, ): void => { - const sqore = new Sqore(circuit, style); - sqore.draw(container, renderDepth); + const sqore = new Sqore(circuit, style); + sqore.draw(container, renderDepth); }; -export { STYLES } from './styles'; +export { STYLES } from "./styles"; // Export types -export type { StyleConfig } from './styles'; -export type { Circuit, Qubit, Operation } from './circuit'; +export type { StyleConfig } from "./styles"; +export type { Circuit, Qubit, Operation } from "./circuit"; diff --git a/circuit_vis/src/metadata.ts b/circuit_vis/src/metadata.ts index 827ac54676..4c5c265289 100644 --- a/circuit_vis/src/metadata.ts +++ b/circuit_vis/src/metadata.ts @@ -1,30 +1,30 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { DataAttributes } from './circuit'; +import { DataAttributes } from "./circuit"; /** * Enum for the various gate operations handled. */ export enum GateType { - /** Measurement gate. */ - Measure, - /** CNOT gate. */ - Cnot, - /** SWAP gate. */ - Swap, - /** X gate. */ - X, - /** Single/multi qubit unitary gate. */ - Unitary, - /** Single/multi controlled unitary gate. */ - ControlledUnitary, - /** Nested group of classically-controlled gates. */ - ClassicalControlled, - /** Group of nested gates */ - Group, - /** Invalid gate. */ - Invalid, + /** Measurement gate. */ + Measure, + /** CNOT gate. */ + Cnot, + /** SWAP gate. */ + Swap, + /** X gate. */ + X, + /** Single/multi qubit unitary gate. */ + Unitary, + /** Single/multi controlled unitary gate. */ + ControlledUnitary, + /** Nested group of classically-controlled gates. */ + ClassicalControlled, + /** Group of nested gates */ + Group, + /** Invalid gate. */ + Invalid, } /** @@ -32,25 +32,25 @@ export enum GateType { * operation for rendering its corresponding SVG. */ export interface Metadata { - /** Gate type. */ - type: GateType; - /** Centre x coord for gate position. */ - x: number; - /** Array of y coords of control registers. */ - controlsY: number[]; - /** Array of y coords of target registers. - * For `GateType.Unitary` or `GateType.ControlledUnitary`, this is an array of groups of - * y coords, where each group represents a unitary box to be rendered separately. - */ - targetsY: (number | number[])[]; - /** Gate label. */ - label: string; - /** Gate arguments as string. */ - displayArgs?: string; - /** Gate width. */ - width: number; - /** Children operations as part of group. */ - children?: (Metadata | Metadata[])[]; - /** Custom data attributes to attach to gate element. */ - dataAttributes?: DataAttributes; + /** Gate type. */ + type: GateType; + /** Centre x coord for gate position. */ + x: number; + /** Array of y coords of control registers. */ + controlsY: number[]; + /** Array of y coords of target registers. + * For `GateType.Unitary` or `GateType.ControlledUnitary`, this is an array of groups of + * y coords, where each group represents a unitary box to be rendered separately. + */ + targetsY: (number | number[])[]; + /** Gate label. */ + label: string; + /** Gate arguments as string. */ + displayArgs?: string; + /** Gate width. */ + width: number; + /** Children operations as part of group. */ + children?: (Metadata | Metadata[])[]; + /** Custom data attributes to attach to gate element. */ + dataAttributes?: DataAttributes; } diff --git a/circuit_vis/src/process.ts b/circuit_vis/src/process.ts index 5c21f7f0fe..d896cb590e 100644 --- a/circuit_vis/src/process.ts +++ b/circuit_vis/src/process.ts @@ -1,11 +1,17 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { minGateWidth, startX, gatePadding, controlBtnOffset, groupBoxPadding } from './constants'; -import { Operation, ConditionalRender } from './circuit'; -import { Metadata, GateType } from './metadata'; -import { Register, RegisterMap, RegisterType } from './register'; -import { getGateWidth } from './utils'; +import { + minGateWidth, + startX, + gatePadding, + controlBtnOffset, + groupBoxPadding, +} from "./constants"; +import { Operation, ConditionalRender } from "./circuit"; +import { Metadata, GateType } from "./metadata"; +import { Register, RegisterMap, RegisterType } from "./register"; +import { getGateWidth } from "./utils"; /** * Takes in a list of operations and maps them to `metadata` objects which @@ -18,73 +24,91 @@ import { getGateWidth } from './utils'; * `svgWidth` which is the width of the entire SVG. */ const processOperations = ( - operations: Operation[], - registers: RegisterMap, + operations: Operation[], + registers: RegisterMap, ): { metadataList: Metadata[]; svgWidth: number } => { - if (operations.length === 0) return { metadataList: [], svgWidth: startX }; - - // Group operations based on registers - const groupedOps: number[][] = _groupOperations(operations, registers); - - // Align operations on multiple registers - const alignedOps: (number | null)[][] = _alignOps(groupedOps); - - // Maintain widths of each column to account for variable-sized gates - const numColumns: number = Math.max(0, ...alignedOps.map((ops) => ops.length)); - const columnsWidths: number[] = new Array(numColumns).fill(minGateWidth); - - // Get classical registers and their starting column index - const classicalRegs: [number, Register][] = _getClassicalRegStart(operations, alignedOps); - - // Keep track of which ops are already seen to avoid duplicate rendering - const visited: { [opIdx: number]: boolean } = {}; - - // Map operation index to gate metadata for formatting later - const opsMetadata: Metadata[][] = alignedOps.map((regOps) => - regOps.map((opIdx, col) => { - let op: Operation | null = null; - - if (opIdx != null && !visited.hasOwnProperty(opIdx)) { - op = operations[opIdx]; - visited[opIdx] = true; - } - - const metadata: Metadata = _opToMetadata(op, registers); - - if (op != null && [GateType.Unitary, GateType.ControlledUnitary].includes(metadata.type)) { - // If gate is a unitary type, split targetsY into groups if there - // is a classical register between them for rendering - - // Get y coordinates of classical registers in the same column as this operation - const classicalRegY: number[] = classicalRegs - .filter(([regCol, _]) => regCol <= col) - .map(([_, reg]) => { - if (reg.cId == null) throw new Error('Could not find cId for classical register.'); - const { children } = registers[reg.qId]; - if (children == null) - throw new Error(`Failed to find classical registers for qubit ID ${reg.qId}.`); - return children[reg.cId].y; - }); + if (operations.length === 0) return { metadataList: [], svgWidth: startX }; + + // Group operations based on registers + const groupedOps: number[][] = _groupOperations(operations, registers); + + // Align operations on multiple registers + const alignedOps: (number | null)[][] = _alignOps(groupedOps); + + // Maintain widths of each column to account for variable-sized gates + const numColumns: number = Math.max( + 0, + ...alignedOps.map((ops) => ops.length), + ); + const columnsWidths: number[] = new Array(numColumns).fill(minGateWidth); + + // Get classical registers and their starting column index + const classicalRegs: [number, Register][] = _getClassicalRegStart( + operations, + alignedOps, + ); + + // Keep track of which ops are already seen to avoid duplicate rendering + const visited: { [opIdx: number]: boolean } = {}; + + // Map operation index to gate metadata for formatting later + const opsMetadata: Metadata[][] = alignedOps.map((regOps) => + regOps.map((opIdx, col) => { + let op: Operation | null = null; + + if (opIdx != null && !visited.hasOwnProperty(opIdx)) { + op = operations[opIdx]; + visited[opIdx] = true; + } + + const metadata: Metadata = _opToMetadata(op, registers); + + if ( + op != null && + [GateType.Unitary, GateType.ControlledUnitary].includes(metadata.type) + ) { + // If gate is a unitary type, split targetsY into groups if there + // is a classical register between them for rendering + + // Get y coordinates of classical registers in the same column as this operation + const classicalRegY: number[] = classicalRegs + .filter(([regCol, _]) => regCol <= col) + .map(([_, reg]) => { + if (reg.cId == null) + throw new Error("Could not find cId for classical register."); + const { children } = registers[reg.qId]; + if (children == null) + throw new Error( + `Failed to find classical registers for qubit ID ${reg.qId}.`, + ); + return children[reg.cId].y; + }); + + metadata.targetsY = _splitTargetsY( + op.targets, + classicalRegY, + registers, + ); + } - metadata.targetsY = _splitTargetsY(op.targets, classicalRegY, registers); - } + // Expand column size, if needed + if (metadata.width > columnsWidths[col]) { + columnsWidths[col] = metadata.width; + } - // Expand column size, if needed - if (metadata.width > columnsWidths[col]) { - columnsWidths[col] = metadata.width; - } + return metadata; + }), + ); - return metadata; - }), - ); + // Fill in x coord of each gate + const endX: number = _fillMetadataX(opsMetadata, columnsWidths); - // Fill in x coord of each gate - const endX: number = _fillMetadataX(opsMetadata, columnsWidths); + // Flatten operations and filter out invalid gates + const metadataList: Metadata[] = opsMetadata + .flat() + .filter(({ type }) => type != GateType.Invalid); - // Flatten operations and filter out invalid gates - const metadataList: Metadata[] = opsMetadata.flat().filter(({ type }) => type != GateType.Invalid); - - return { metadataList, svgWidth: endX }; + return { metadataList, svgWidth: endX }; }; /** @@ -96,33 +120,41 @@ const processOperations = ( * @returns 2D array of indices where `groupedOps[i][j]` is the index of the operations * at register `i` and column `j` (not yet aligned/padded). */ -const _groupOperations = (operations: Operation[], registers: RegisterMap): number[][] => { - // NOTE: We get the max ID instead of just number of keys because there can be a qubit ID that - // isn't acted upon and thus does not show up as a key in registers. - const numRegs: number = Math.max(-1, ...Object.keys(registers).map(Number)) + 1; - const groupedOps: number[][] = Array.from(Array(numRegs), () => new Array(0)); - operations.forEach(({ targets, controls }, instrIdx) => { - const ctrls: Register[] = controls || []; - const qRegs: Register[] = [...ctrls, ...targets].filter( - ({ type }) => (type || RegisterType.Qubit) === RegisterType.Qubit, - ); - const qRegIdxList: number[] = qRegs.map(({ qId }) => qId); - const clsControls: Register[] = ctrls.filter( - ({ type }) => (type || RegisterType.Qubit) === RegisterType.Classical, - ); - const isClassicallyControlled: boolean = clsControls.length > 0; - if (!isClassicallyControlled && qRegs.length === 0) return; - // If operation is classically-controlled, pad all qubit registers. Otherwise, only pad - // the contiguous range of registers that it covers. - const minRegIdx: number = isClassicallyControlled ? 0 : Math.min(...qRegIdxList); - const maxRegIdx: number = isClassicallyControlled ? numRegs - 1 : Math.max(...qRegIdxList); - // Add operation also to registers that are in-between target registers - // so that other gates won't render in the middle. - for (let i = minRegIdx; i <= maxRegIdx; i++) { - groupedOps[i].push(instrIdx); - } - }); - return groupedOps; +const _groupOperations = ( + operations: Operation[], + registers: RegisterMap, +): number[][] => { + // NOTE: We get the max ID instead of just number of keys because there can be a qubit ID that + // isn't acted upon and thus does not show up as a key in registers. + const numRegs: number = + Math.max(-1, ...Object.keys(registers).map(Number)) + 1; + const groupedOps: number[][] = Array.from(Array(numRegs), () => new Array(0)); + operations.forEach(({ targets, controls }, instrIdx) => { + const ctrls: Register[] = controls || []; + const qRegs: Register[] = [...ctrls, ...targets].filter( + ({ type }) => (type || RegisterType.Qubit) === RegisterType.Qubit, + ); + const qRegIdxList: number[] = qRegs.map(({ qId }) => qId); + const clsControls: Register[] = ctrls.filter( + ({ type }) => (type || RegisterType.Qubit) === RegisterType.Classical, + ); + const isClassicallyControlled: boolean = clsControls.length > 0; + if (!isClassicallyControlled && qRegs.length === 0) return; + // If operation is classically-controlled, pad all qubit registers. Otherwise, only pad + // the contiguous range of registers that it covers. + const minRegIdx: number = isClassicallyControlled + ? 0 + : Math.min(...qRegIdxList); + const maxRegIdx: number = isClassicallyControlled + ? numRegs - 1 + : Math.max(...qRegIdxList); + // Add operation also to registers that are in-between target registers + // so that other gates won't render in the middle. + for (let i = minRegIdx; i <= maxRegIdx; i++) { + groupedOps[i].push(instrIdx); + } + }); + return groupedOps; }; /** @@ -137,31 +169,33 @@ const _groupOperations = (operations: Operation[], registers: RegisterMap): numb * @returns 2D array of aligned operations padded with `null`s. */ const _alignOps = (ops: number[][]): (number | null)[][] => { - let maxNumOps: number = Math.max(0, ...ops.map((regOps) => regOps.length)); - let col = 0; - // Deep copy ops to be returned as paddedOps - const paddedOps: (number | null)[][] = JSON.parse(JSON.stringify(ops)); - while (col < maxNumOps) { - for (let regIdx = 0; regIdx < paddedOps.length; regIdx++) { - const reg: (number | null)[] = paddedOps[regIdx]; - if (reg.length <= col) continue; - - // Should never be null (nulls are only padded to previous columns) - const opIdx: number | null = reg[col]; - - // Get position of gate - const targetsPos: number[] = paddedOps.map((regOps) => regOps.indexOf(opIdx)); - const gatePos: number = Math.max(-1, ...targetsPos); - - // If current column is not desired gate position, pad with null - if (col < gatePos) { - paddedOps[regIdx].splice(col, 0, null); - maxNumOps = Math.max(maxNumOps, paddedOps[regIdx].length); - } - } - col++; + let maxNumOps: number = Math.max(0, ...ops.map((regOps) => regOps.length)); + let col = 0; + // Deep copy ops to be returned as paddedOps + const paddedOps: (number | null)[][] = JSON.parse(JSON.stringify(ops)); + while (col < maxNumOps) { + for (let regIdx = 0; regIdx < paddedOps.length; regIdx++) { + const reg: (number | null)[] = paddedOps[regIdx]; + if (reg.length <= col) continue; + + // Should never be null (nulls are only padded to previous columns) + const opIdx: number | null = reg[col]; + + // Get position of gate + const targetsPos: number[] = paddedOps.map((regOps) => + regOps.indexOf(opIdx), + ); + const gatePos: number = Math.max(-1, ...targetsPos); + + // If current column is not desired gate position, pad with null + if (col < gatePos) { + paddedOps[regIdx].splice(col, 0, null); + maxNumOps = Math.max(maxNumOps, paddedOps[regIdx].length); + } } - return paddedOps; + col++; + } + return paddedOps; }; /** @@ -172,20 +206,23 @@ const _alignOps = (ops: number[][]): (number | null)[][] => { * * @returns Array of classical register and their starting column indices in the form [[column, register]]. */ -const _getClassicalRegStart = (ops: Operation[], idxList: (number | null)[][]): [number, Register][] => { - const clsRegs: [number, Register][] = []; - idxList.forEach((reg) => { - for (let col = 0; col < reg.length; col++) { - const opIdx: number | null = reg[col]; - if (opIdx != null && ops[opIdx].isMeasurement) { - const targetClsRegs: Register[] = ops[opIdx].targets.filter( - (reg) => reg.type === RegisterType.Classical, - ); - targetClsRegs.forEach((reg) => clsRegs.push([col, reg])); - } - } - }); - return clsRegs; +const _getClassicalRegStart = ( + ops: Operation[], + idxList: (number | null)[][], +): [number, Register][] => { + const clsRegs: [number, Register][] = []; + idxList.forEach((reg) => { + for (let col = 0; col < reg.length; col++) { + const opIdx: number | null = reg[col]; + if (opIdx != null && ops[opIdx].isMeasurement) { + const targetClsRegs: Register[] = ops[opIdx].targets.filter( + (reg) => reg.type === RegisterType.Classical, + ); + targetClsRegs.forEach((reg) => clsRegs.push([col, reg])); + } + } + }); + return clsRegs; }; /** @@ -197,103 +234,122 @@ const _getClassicalRegStart = (ops: Operation[], idxList: (number | null)[][]): * * @returns Metadata representation of given operation. */ -const _opToMetadata = (op: Operation | null, registers: RegisterMap): Metadata => { - const metadata: Metadata = { - type: GateType.Invalid, - x: 0, - controlsY: [], - targetsY: [], - label: '', - width: -1, - }; - - if (op == null) return metadata; - - const { - gate, - dataAttributes, - displayArgs, - isMeasurement, - isConditional, - isControlled, - isAdjoint, - controls, - targets, - children, - conditionalRender, - } = op; - - // Set y coords - metadata.controlsY = controls?.map((reg) => _getRegY(reg, registers)) || []; - metadata.targetsY = targets.map((reg) => _getRegY(reg, registers)); - - if (isConditional) { - // Classically-controlled operations - if (children == null || children.length == 0) - throw new Error('No children operations found for classically-controlled operation.'); - - // Gates to display when classical bit is 0. - const onZeroOps: Operation[] = children.filter((op) => op.conditionalRender !== ConditionalRender.OnOne); - let childrenInstrs = processOperations(onZeroOps, registers); - const zeroGates: Metadata[] = childrenInstrs.metadataList; - const zeroChildWidth: number = childrenInstrs.svgWidth; - - // Gates to display when classical bit is 1. - const onOneOps: Operation[] = children.filter((op) => op.conditionalRender !== ConditionalRender.OnZero); - childrenInstrs = processOperations(onOneOps, registers); - const oneGates: Metadata[] = childrenInstrs.metadataList; - const oneChildWidth: number = childrenInstrs.svgWidth; - - // Subtract startX (left-side) and 2*gatePadding (right-side) from nested child gates width - const width: number = Math.max(zeroChildWidth, oneChildWidth) - startX - gatePadding * 2; - - metadata.type = GateType.ClassicalControlled; - metadata.children = [zeroGates, oneGates]; - // Add additional width from control button and inner box padding for dashed box - metadata.width = width + controlBtnOffset + groupBoxPadding * 2; - - // Set targets to first and last quantum registers so we can render the surrounding box - // around all quantum registers. - const qubitsY: number[] = Object.values(registers).map(({ y }) => y); - if (qubitsY.length > 0) metadata.targetsY = [Math.min(...qubitsY), Math.max(...qubitsY)]; - } else if (conditionalRender == ConditionalRender.AsGroup && (children?.length || 0) > 0) { - const childrenInstrs = processOperations(children as Operation[], registers); - metadata.type = GateType.Group; - metadata.children = childrenInstrs.metadataList; - // _zoomButton function in gateFormatter.ts relies on - // 'expanded' attribute to render zoom button - metadata.dataAttributes = { expanded: 'true' }; - // Subtract startX (left-side) and add inner box padding (minus nested gate padding) for dashed box - metadata.width = childrenInstrs.svgWidth - startX + (groupBoxPadding - gatePadding) * 2; - } else if (isMeasurement) { - metadata.type = GateType.Measure; - } else if (gate === 'SWAP') { - metadata.type = GateType.Swap; - } else if (isControlled) { - metadata.type = gate === 'X' ? GateType.Cnot : GateType.ControlledUnitary; - metadata.label = gate; - } else if (gate === 'X') { - metadata.type = GateType.X; - metadata.label = gate; - } else { - // Any other gate treated as a simple unitary gate - metadata.type = GateType.Unitary; - metadata.label = gate; - } - - // If adjoint, add ' to the end of gate label - if (isAdjoint && metadata.label.length > 0) metadata.label += "'"; - - // If gate has extra arguments, display them - if (displayArgs != null) metadata.displayArgs = displayArgs; - - // Set gate width - metadata.width = getGateWidth(metadata); - - // Extend existing data attributes with user-provided data attributes - if (dataAttributes != null) metadata.dataAttributes = { ...metadata.dataAttributes, ...dataAttributes }; +const _opToMetadata = ( + op: Operation | null, + registers: RegisterMap, +): Metadata => { + const metadata: Metadata = { + type: GateType.Invalid, + x: 0, + controlsY: [], + targetsY: [], + label: "", + width: -1, + }; + + if (op == null) return metadata; + + const { + gate, + dataAttributes, + displayArgs, + isMeasurement, + isConditional, + isControlled, + isAdjoint, + controls, + targets, + children, + conditionalRender, + } = op; + + // Set y coords + metadata.controlsY = controls?.map((reg) => _getRegY(reg, registers)) || []; + metadata.targetsY = targets.map((reg) => _getRegY(reg, registers)); + + if (isConditional) { + // Classically-controlled operations + if (children == null || children.length == 0) + throw new Error( + "No children operations found for classically-controlled operation.", + ); + + // Gates to display when classical bit is 0. + const onZeroOps: Operation[] = children.filter( + (op) => op.conditionalRender !== ConditionalRender.OnOne, + ); + let childrenInstrs = processOperations(onZeroOps, registers); + const zeroGates: Metadata[] = childrenInstrs.metadataList; + const zeroChildWidth: number = childrenInstrs.svgWidth; - return metadata; + // Gates to display when classical bit is 1. + const onOneOps: Operation[] = children.filter( + (op) => op.conditionalRender !== ConditionalRender.OnZero, + ); + childrenInstrs = processOperations(onOneOps, registers); + const oneGates: Metadata[] = childrenInstrs.metadataList; + const oneChildWidth: number = childrenInstrs.svgWidth; + + // Subtract startX (left-side) and 2*gatePadding (right-side) from nested child gates width + const width: number = + Math.max(zeroChildWidth, oneChildWidth) - startX - gatePadding * 2; + + metadata.type = GateType.ClassicalControlled; + metadata.children = [zeroGates, oneGates]; + // Add additional width from control button and inner box padding for dashed box + metadata.width = width + controlBtnOffset + groupBoxPadding * 2; + + // Set targets to first and last quantum registers so we can render the surrounding box + // around all quantum registers. + const qubitsY: number[] = Object.values(registers).map(({ y }) => y); + if (qubitsY.length > 0) + metadata.targetsY = [Math.min(...qubitsY), Math.max(...qubitsY)]; + } else if ( + conditionalRender == ConditionalRender.AsGroup && + (children?.length || 0) > 0 + ) { + const childrenInstrs = processOperations( + children as Operation[], + registers, + ); + metadata.type = GateType.Group; + metadata.children = childrenInstrs.metadataList; + // _zoomButton function in gateFormatter.ts relies on + // 'expanded' attribute to render zoom button + metadata.dataAttributes = { expanded: "true" }; + // Subtract startX (left-side) and add inner box padding (minus nested gate padding) for dashed box + metadata.width = + childrenInstrs.svgWidth - startX + (groupBoxPadding - gatePadding) * 2; + } else if (isMeasurement) { + metadata.type = GateType.Measure; + } else if (gate === "SWAP") { + metadata.type = GateType.Swap; + } else if (isControlled) { + metadata.type = gate === "X" ? GateType.Cnot : GateType.ControlledUnitary; + metadata.label = gate; + } else if (gate === "X") { + metadata.type = GateType.X; + metadata.label = gate; + } else { + // Any other gate treated as a simple unitary gate + metadata.type = GateType.Unitary; + metadata.label = gate; + } + + // If adjoint, add ' to the end of gate label + if (isAdjoint && metadata.label.length > 0) metadata.label += "'"; + + // If gate has extra arguments, display them + if (displayArgs != null) metadata.displayArgs = displayArgs; + + // Set gate width + metadata.width = getGateWidth(metadata); + + // Extend existing data attributes with user-provided data attributes + if (dataAttributes != null) + metadata.dataAttributes = { ...metadata.dataAttributes, ...dataAttributes }; + + return metadata; }; /** @@ -305,25 +361,31 @@ const _opToMetadata = (op: Operation | null, registers: RegisterMap): Metadata = * @returns The y coord of give register. */ const _getRegY = (reg: Register, registers: RegisterMap): number => { - const { type, qId, cId } = reg; - if (!registers.hasOwnProperty(qId)) throw new Error(`ERROR: Qubit register with ID ${qId} not found.`); - const { y, children } = registers[qId]; - switch (type) { - case undefined: - case RegisterType.Qubit: - return y; - case RegisterType.Classical: - if (children == null) throw new Error(`ERROR: No classical registers found for qubit ID ${qId}.`); - if (cId == null) - throw new Error(`ERROR: No ID defined for classical register associated with qubit ID ${qId}.`); - if (children.length <= cId) - throw new Error( - `ERROR: Classical register ID ${cId} invalid for qubit ID ${qId} with ${children.length} classical register(s).`, - ); - return children[cId].y; - default: - throw new Error(`ERROR: Unknown register type ${type}.`); - } + const { type, qId, cId } = reg; + if (!registers.hasOwnProperty(qId)) + throw new Error(`ERROR: Qubit register with ID ${qId} not found.`); + const { y, children } = registers[qId]; + switch (type) { + case undefined: + case RegisterType.Qubit: + return y; + case RegisterType.Classical: + if (children == null) + throw new Error( + `ERROR: No classical registers found for qubit ID ${qId}.`, + ); + if (cId == null) + throw new Error( + `ERROR: No ID defined for classical register associated with qubit ID ${qId}.`, + ); + if (children.length <= cId) + throw new Error( + `ERROR: Classical register ID ${cId} invalid for qubit ID ${qId} with ${children.length} classical register(s).`, + ); + return children[cId].y; + default: + throw new Error(`ERROR: Unknown register type ${type}.`); + } }; /** @@ -335,48 +397,57 @@ const _getRegY = (reg: Register, registers: RegisterMap): number => { * * @returns Groups of target qubit y coords. */ -const _splitTargetsY = (targets: Register[], classicalRegY: number[], registers: RegisterMap): number[][] => { - if (targets.length === 0) return []; - - // Get qIds sorted by ascending y value - const orderedQIds: number[] = Object.keys(registers).map(Number); - orderedQIds.sort((a, b) => registers[a].y - registers[b].y); - const qIdPosition: { [qId: number]: number } = {}; - orderedQIds.forEach((qId, i) => (qIdPosition[qId] = i)); - - // Sort targets and classicalRegY by ascending y value - targets = targets.slice(); - targets.sort((a, b) => { - const posDiff: number = qIdPosition[a.qId] - qIdPosition[b.qId]; - if (posDiff === 0 && a.cId != null && b.cId != null) return a.cId - b.cId; - else return posDiff; - }); - classicalRegY = classicalRegY.slice(); - classicalRegY.sort((a, b) => a - b); - - let prevPos = 0; - let prevY = 0; - - return targets.reduce((groups: number[][], target: Register) => { - const y = _getRegY(target, registers); - const pos = qIdPosition[target.qId]; - - // Split into new group if one of the following holds: - // 1. First target register - // 2. Non-adjacent qubit registers - // 3. There is a classical register between current and previous register - if (groups.length === 0 || pos > prevPos + 1 || (classicalRegY[0] > prevY && classicalRegY[0] < y)) - groups.push([y]); - else groups[groups.length - 1].push(y); - - prevPos = pos; - prevY = y; - - // Remove classical registers that are higher than current y - while (classicalRegY.length > 0 && classicalRegY[0] <= y) classicalRegY.shift(); - - return groups; - }, []); +const _splitTargetsY = ( + targets: Register[], + classicalRegY: number[], + registers: RegisterMap, +): number[][] => { + if (targets.length === 0) return []; + + // Get qIds sorted by ascending y value + const orderedQIds: number[] = Object.keys(registers).map(Number); + orderedQIds.sort((a, b) => registers[a].y - registers[b].y); + const qIdPosition: { [qId: number]: number } = {}; + orderedQIds.forEach((qId, i) => (qIdPosition[qId] = i)); + + // Sort targets and classicalRegY by ascending y value + targets = targets.slice(); + targets.sort((a, b) => { + const posDiff: number = qIdPosition[a.qId] - qIdPosition[b.qId]; + if (posDiff === 0 && a.cId != null && b.cId != null) return a.cId - b.cId; + else return posDiff; + }); + classicalRegY = classicalRegY.slice(); + classicalRegY.sort((a, b) => a - b); + + let prevPos = 0; + let prevY = 0; + + return targets.reduce((groups: number[][], target: Register) => { + const y = _getRegY(target, registers); + const pos = qIdPosition[target.qId]; + + // Split into new group if one of the following holds: + // 1. First target register + // 2. Non-adjacent qubit registers + // 3. There is a classical register between current and previous register + if ( + groups.length === 0 || + pos > prevPos + 1 || + (classicalRegY[0] > prevY && classicalRegY[0] < y) + ) + groups.push([y]); + else groups[groups.length - 1].push(y); + + prevPos = pos; + prevY = y; + + // Remove classical registers that are higher than current y + while (classicalRegY.length > 0 && classicalRegY[0] <= y) + classicalRegY.shift(); + + return groups; + }, []); }; /** @@ -387,43 +458,47 @@ const _splitTargetsY = (targets: Register[], classicalRegY: number[], registers: * * @returns Rightmost x coord. */ -const _fillMetadataX = (opsMetadata: Metadata[][], columnWidths: number[]): number => { - let currX: number = startX; - - const colStartX: number[] = columnWidths.map((width) => { - const x: number = currX; - currX += width + gatePadding * 2; - return x; - }); - - const endX: number = currX; - - opsMetadata.forEach((regOps) => - regOps.forEach((metadata, col) => { - const x = colStartX[col]; - switch (metadata.type) { - case GateType.ClassicalControlled: - case GateType.Group: - // Subtract startX offset from nested gates and add offset and padding - let offset: number = x - startX + groupBoxPadding; - if (metadata.type === GateType.ClassicalControlled) offset += controlBtnOffset; - - // Offset each x coord in children gates - _offsetChildrenX(metadata.children, offset); - - // We don't use the centre x coord because we only care about the rightmost x for - // rendering the box around the group of nested gates - metadata.x = x; - break; - - default: - metadata.x = x + columnWidths[col] / 2; - break; - } - }), - ); +const _fillMetadataX = ( + opsMetadata: Metadata[][], + columnWidths: number[], +): number => { + let currX: number = startX; + + const colStartX: number[] = columnWidths.map((width) => { + const x: number = currX; + currX += width + gatePadding * 2; + return x; + }); + + const endX: number = currX; + + opsMetadata.forEach((regOps) => + regOps.forEach((metadata, col) => { + const x = colStartX[col]; + switch (metadata.type) { + case GateType.ClassicalControlled: + case GateType.Group: + // Subtract startX offset from nested gates and add offset and padding + let offset: number = x - startX + groupBoxPadding; + if (metadata.type === GateType.ClassicalControlled) + offset += controlBtnOffset; + + // Offset each x coord in children gates + _offsetChildrenX(metadata.children, offset); + + // We don't use the centre x coord because we only care about the rightmost x for + // rendering the box around the group of nested gates + metadata.x = x; + break; + + default: + metadata.x = x + columnWidths[col] / 2; + break; + } + }), + ); - return endX; + return endX; }; /** @@ -432,22 +507,25 @@ const _fillMetadataX = (opsMetadata: Metadata[][], columnWidths: number[]): numb * @param children 2D array of children metadata. * @param offset x coord offset. */ -const _offsetChildrenX = (children: (Metadata | Metadata[])[] | undefined, offset: number): void => { - if (children == null) return; - children.flat().forEach((child) => { - child.x += offset; - _offsetChildrenX(child.children, offset); - }); +const _offsetChildrenX = ( + children: (Metadata | Metadata[])[] | undefined, + offset: number, +): void => { + if (children == null) return; + children.flat().forEach((child) => { + child.x += offset; + _offsetChildrenX(child.children, offset); + }); }; export { - processOperations, - _groupOperations, - _alignOps, - _getClassicalRegStart, - _opToMetadata, - _getRegY, - _splitTargetsY, - _fillMetadataX, - _offsetChildrenX, + processOperations, + _groupOperations, + _alignOps, + _getClassicalRegStart, + _opToMetadata, + _getRegY, + _splitTargetsY, + _fillMetadataX, + _offsetChildrenX, }; diff --git a/circuit_vis/src/register.ts b/circuit_vis/src/register.ts index cdc28dab91..e2fb0588fa 100644 --- a/circuit_vis/src/register.ts +++ b/circuit_vis/src/register.ts @@ -5,37 +5,37 @@ * Type of register. */ export enum RegisterType { - Qubit, - Classical, + Qubit, + Classical, } /** * Represents a register resource. */ export interface Register { - /** Type of register. If missing defaults to Qubit. */ - type?: RegisterType; - /** Qubit register ID. */ - qId: number; - /** Classical register ID (if classical register). */ - cId?: number; + /** Type of register. If missing defaults to Qubit. */ + type?: RegisterType; + /** Qubit register ID. */ + qId: number; + /** Classical register ID (if classical register). */ + cId?: number; } /** * Metadata for qubit register. */ export interface RegisterMetadata { - /** Type of register. */ - type: RegisterType; - /** y coord of register */ - y: number; - /** Nested classical registers attached to quantum register. */ - children?: RegisterMetadata[]; + /** Type of register. */ + type: RegisterType; + /** y coord of register */ + y: number; + /** Nested classical registers attached to quantum register. */ + children?: RegisterMetadata[]; } /** * Mapping from qubit IDs to their register metadata. */ export interface RegisterMap { - [id: number]: RegisterMetadata; + [id: number]: RegisterMetadata; } diff --git a/circuit_vis/src/sqore.ts b/circuit_vis/src/sqore.ts index c20ba65c75..f3899739a5 100644 --- a/circuit_vis/src/sqore.ts +++ b/circuit_vis/src/sqore.ts @@ -1,26 +1,26 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { formatInputs } from './formatters/inputFormatter'; -import { formatGates } from './formatters/gateFormatter'; -import { formatRegisters } from './formatters/registerFormatter'; -import { processOperations } from './process'; -import { ConditionalRender, Circuit, Operation } from './circuit'; -import { Metadata, GateType } from './metadata'; -import { StyleConfig, style, STYLES } from './styles'; -import { createUUID } from './utils'; -import { svgNS } from './constants'; +import { formatInputs } from "./formatters/inputFormatter"; +import { formatGates } from "./formatters/gateFormatter"; +import { formatRegisters } from "./formatters/registerFormatter"; +import { processOperations } from "./process"; +import { ConditionalRender, Circuit, Operation } from "./circuit"; +import { Metadata, GateType } from "./metadata"; +import { StyleConfig, style, STYLES } from "./styles"; +import { createUUID } from "./utils"; +import { svgNS } from "./constants"; /** * Contains metadata for visualization. */ interface ComposedSqore { - /** Width of visualization. */ - width: number; - /** Height of visualization. */ - height: number; - /** SVG elements the make up the visualization. */ - elements: SVGElement[]; + /** Width of visualization. */ + width: number; + /** Height of visualization. */ + height: number; + /** SVG elements the make up the visualization. */ + elements: SVGElement[]; } /** @@ -28,324 +28,347 @@ interface ComposedSqore { * interactivity. */ type GateRegistry = { - [id: string]: Operation; + [id: string]: Operation; }; /** * Entrypoint class for rendering circuit visualizations. */ export class Sqore { - circuit: Circuit; - style: StyleConfig = {}; - gateRegistry: GateRegistry = {}; + circuit: Circuit; + style: StyleConfig = {}; + gateRegistry: GateRegistry = {}; - /** - * Initializes Sqore object with custom styles. - * - * @param circuit Circuit to be visualized. - * @param style Custom visualization style. - */ - constructor(circuit: Circuit, style: StyleConfig | string = {}) { - this.circuit = circuit; - this.style = this.getStyle(style); - } - - /** - * Render circuit into `container` at the specified layer depth. - * - * @param container HTML element for rendering visualization into. - * @param renderDepth Initial layer depth at which to render gates. - */ - draw(container: HTMLElement, renderDepth = 0): void { - // Inject into container - if (container == null) throw new Error(`Container not provided.`); + /** + * Initializes Sqore object with custom styles. + * + * @param circuit Circuit to be visualized. + * @param style Custom visualization style. + */ + constructor(circuit: Circuit, style: StyleConfig | string = {}) { + this.circuit = circuit; + this.style = this.getStyle(style); + } - // Create copy of circuit to prevent mutation - const circuit: Circuit = JSON.parse(JSON.stringify(this.circuit)); + /** + * Render circuit into `container` at the specified layer depth. + * + * @param container HTML element for rendering visualization into. + * @param renderDepth Initial layer depth at which to render gates. + */ + draw(container: HTMLElement, renderDepth = 0): void { + // Inject into container + if (container == null) throw new Error(`Container not provided.`); - // Assign unique IDs to each operation - circuit.operations.forEach((op, i) => this.fillGateRegistry(op, i.toString())); + // Create copy of circuit to prevent mutation + const circuit: Circuit = JSON.parse(JSON.stringify(this.circuit)); - // Render operations at starting at given depth - circuit.operations = this.selectOpsAtDepth(circuit.operations, renderDepth); + // Assign unique IDs to each operation + circuit.operations.forEach((op, i) => + this.fillGateRegistry(op, i.toString()), + ); - // If only one top-level operation, expand automatically: - if ( - circuit.operations.length == 1 && - circuit.operations[0].dataAttributes != null && - circuit.operations[0].dataAttributes.hasOwnProperty('id') - ) { - const id: string = circuit.operations[0].dataAttributes['id']; - this.expandOperation(circuit.operations, id); - } + // Render operations at starting at given depth + circuit.operations = this.selectOpsAtDepth(circuit.operations, renderDepth); - this.renderCircuit(container, circuit); + // If only one top-level operation, expand automatically: + if ( + circuit.operations.length == 1 && + circuit.operations[0].dataAttributes != null && + circuit.operations[0].dataAttributes.hasOwnProperty("id") + ) { + const id: string = circuit.operations[0].dataAttributes["id"]; + this.expandOperation(circuit.operations, id); } - /** - * Retrieve style for visualization. - * - * @param style Custom style or style name. - * - * @returns Custom style. - */ - private getStyle(style: StyleConfig | string = {}): StyleConfig { - if (typeof style === 'string' || style instanceof String) { - const styleName: string = style as string; - if (!STYLES.hasOwnProperty(styleName)) { - console.error(`No style ${styleName} found in STYLES.`); - return {}; - } - style = STYLES[styleName]; - } - return style; - } + this.renderCircuit(container, circuit); + } - /** - * Render circuit into `container`. - * - * @param container HTML element for rendering visualization into. - * @param circuit Circuit object to be rendered. - */ - private renderCircuit(container: HTMLElement, circuit: Circuit): void { - // Create visualization components - const composedSqore: ComposedSqore = this.compose(circuit); - const svg: SVGElement = this.generateSvg(composedSqore); - container.innerHTML = ''; - container.appendChild(svg); - this.addGateClickHandlers(container, circuit); + /** + * Retrieve style for visualization. + * + * @param style Custom style or style name. + * + * @returns Custom style. + */ + private getStyle(style: StyleConfig | string = {}): StyleConfig { + if (typeof style === "string" || style instanceof String) { + const styleName: string = style as string; + if (!STYLES.hasOwnProperty(styleName)) { + console.error(`No style ${styleName} found in STYLES.`); + return {}; + } + style = STYLES[styleName]; } + return style; + } - /** - * Generates the components required for visualization. - * - * @param circuit Circuit to be visualized. - * - * @returns `ComposedSqore` object containing metadata for visualization. - */ - private compose(circuit: Circuit): ComposedSqore { - const add = (acc: Metadata[], gate: Metadata | Metadata[]): void => { - if (Array.isArray(gate)) { - gate.forEach((g) => add(acc, g)); - } else { - acc.push(gate); - gate.children?.forEach((g) => add(acc, g)); - } - }; + /** + * Render circuit into `container`. + * + * @param container HTML element for rendering visualization into. + * @param circuit Circuit object to be rendered. + */ + private renderCircuit(container: HTMLElement, circuit: Circuit): void { + // Create visualization components + const composedSqore: ComposedSqore = this.compose(circuit); + const svg: SVGElement = this.generateSvg(composedSqore); + container.innerHTML = ""; + container.appendChild(svg); + this.addGateClickHandlers(container, circuit); + } - const flatten = (gates: Metadata[]): Metadata[] => { - const result: Metadata[] = []; - add(result, gates); - return result; - }; + /** + * Generates the components required for visualization. + * + * @param circuit Circuit to be visualized. + * + * @returns `ComposedSqore` object containing metadata for visualization. + */ + private compose(circuit: Circuit): ComposedSqore { + const add = (acc: Metadata[], gate: Metadata | Metadata[]): void => { + if (Array.isArray(gate)) { + gate.forEach((g) => add(acc, g)); + } else { + acc.push(gate); + gate.children?.forEach((g) => add(acc, g)); + } + }; - const { qubits, operations } = circuit; - const { qubitWires, registers, svgHeight } = formatInputs(qubits); - const { metadataList, svgWidth } = processOperations(operations, registers); - const formattedGates: SVGElement = formatGates(metadataList); - const measureGates: Metadata[] = flatten(metadataList).filter(({ type }) => type === GateType.Measure); - const formattedRegs: SVGElement = formatRegisters(registers, measureGates, svgWidth); + const flatten = (gates: Metadata[]): Metadata[] => { + const result: Metadata[] = []; + add(result, gates); + return result; + }; - const composedSqore: ComposedSqore = { - width: svgWidth, - height: svgHeight, - elements: [qubitWires, formattedRegs, formattedGates], - }; - return composedSqore; - } + const { qubits, operations } = circuit; + const { qubitWires, registers, svgHeight } = formatInputs(qubits); + const { metadataList, svgWidth } = processOperations(operations, registers); + const formattedGates: SVGElement = formatGates(metadataList); + const measureGates: Metadata[] = flatten(metadataList).filter( + ({ type }) => type === GateType.Measure, + ); + const formattedRegs: SVGElement = formatRegisters( + registers, + measureGates, + svgWidth, + ); - /** - * Generates visualization of `composedSqore` as an SVG. - * - * @param composedSqore ComposedSqore to be visualized. - * - * @returns SVG representation of circuit visualization. - */ - private generateSvg(composedSqore: ComposedSqore): SVGElement { - const { width, height, elements } = composedSqore; - const uuid: string = createUUID(); + const composedSqore: ComposedSqore = { + width: svgWidth, + height: svgHeight, + elements: [qubitWires, formattedRegs, formattedGates], + }; + return composedSqore; + } - const svg: SVGElement = document.createElementNS(svgNS, 'svg'); - svg.setAttribute('id', uuid); - svg.setAttribute('class', 'qviz'); - svg.setAttribute('width', width.toString()); - svg.setAttribute('height', height.toString()); - svg.style.setProperty('max-width', 'fit-content'); + /** + * Generates visualization of `composedSqore` as an SVG. + * + * @param composedSqore ComposedSqore to be visualized. + * + * @returns SVG representation of circuit visualization. + */ + private generateSvg(composedSqore: ComposedSqore): SVGElement { + const { width, height, elements } = composedSqore; + const uuid: string = createUUID(); - // Add styles - const css = document.createElement('style'); - css.innerHTML = style(this.style); - svg.appendChild(css); + const svg: SVGElement = document.createElementNS(svgNS, "svg"); + svg.setAttribute("id", uuid); + svg.setAttribute("class", "qviz"); + svg.setAttribute("width", width.toString()); + svg.setAttribute("height", height.toString()); + svg.style.setProperty("max-width", "fit-content"); - // Add body elements - elements.forEach((element: SVGElement) => svg.appendChild(element)); + // Add styles + const css = document.createElement("style"); + css.innerHTML = style(this.style); + svg.appendChild(css); - return svg; - } + // Add body elements + elements.forEach((element: SVGElement) => svg.appendChild(element)); - /** - * Depth-first traversal to assign unique ID to `operation`. - * The operation is assigned the id `id` and its `i`th child is recursively given - * the id `${id}-${i}`. - * - * @param operation Operation to be assigned. - * @param id: ID to assign to `operation`. - * - */ - private fillGateRegistry(operation: Operation, id: string): void { - if (operation.dataAttributes == null) operation.dataAttributes = {}; - operation.dataAttributes['id'] = id; - // By default, operations cannot be zoomed-out - operation.dataAttributes['zoom-out'] = 'false'; - this.gateRegistry[id] = operation; - operation.children?.forEach((childOp, i) => { - this.fillGateRegistry(childOp, `${id}-${i}`); - if (childOp.dataAttributes == null) childOp.dataAttributes = {}; - // Children operations can be zoomed out - childOp.dataAttributes['zoom-out'] = 'true'; - }); - // Composite operations can be zoomed in - operation.dataAttributes['zoom-in'] = (operation.children != null).toString(); - } + return svg; + } - /** - * Pick out operations that are at or below `renderDepth`. - * - * @param operations List of circuit operations. - * @param renderDepth Initial layer depth at which to render gates. - * - * @returns List of operations at or below specifed depth. - */ - private selectOpsAtDepth(operations: Operation[], renderDepth: number): Operation[] { - if (renderDepth < 0) throw new Error(`Invalid renderDepth of ${renderDepth}. Needs to be >= 0.`); - if (renderDepth === 0) return operations; - return operations - .map((op) => (op.children != null ? this.selectOpsAtDepth(op.children, renderDepth - 1) : op)) - .flat(); - } + /** + * Depth-first traversal to assign unique ID to `operation`. + * The operation is assigned the id `id` and its `i`th child is recursively given + * the id `${id}-${i}`. + * + * @param operation Operation to be assigned. + * @param id: ID to assign to `operation`. + * + */ + private fillGateRegistry(operation: Operation, id: string): void { + if (operation.dataAttributes == null) operation.dataAttributes = {}; + operation.dataAttributes["id"] = id; + // By default, operations cannot be zoomed-out + operation.dataAttributes["zoom-out"] = "false"; + this.gateRegistry[id] = operation; + operation.children?.forEach((childOp, i) => { + this.fillGateRegistry(childOp, `${id}-${i}`); + if (childOp.dataAttributes == null) childOp.dataAttributes = {}; + // Children operations can be zoomed out + childOp.dataAttributes["zoom-out"] = "true"; + }); + // Composite operations can be zoomed in + operation.dataAttributes["zoom-in"] = ( + operation.children != null + ).toString(); + } - /** - * Add interactive click handlers to circuit HTML elements. - * - * @param container HTML element containing visualized circuit. - * @param circuit Circuit to be visualized. - * - */ - private addGateClickHandlers(container: HTMLElement, circuit: Circuit): void { - this.addClassicalControlHandlers(container); - this.addZoomHandlers(container, circuit); - } + /** + * Pick out operations that are at or below `renderDepth`. + * + * @param operations List of circuit operations. + * @param renderDepth Initial layer depth at which to render gates. + * + * @returns List of operations at or below specifed depth. + */ + private selectOpsAtDepth( + operations: Operation[], + renderDepth: number, + ): Operation[] { + if (renderDepth < 0) + throw new Error( + `Invalid renderDepth of ${renderDepth}. Needs to be >= 0.`, + ); + if (renderDepth === 0) return operations; + return operations + .map((op) => + op.children != null + ? this.selectOpsAtDepth(op.children, renderDepth - 1) + : op, + ) + .flat(); + } - /** - * Add interactive click handlers for classically-controlled operations. - * - * @param container HTML element containing visualized circuit. - * - */ - private addClassicalControlHandlers(container: HTMLElement): void { - container.querySelectorAll('.classically-controlled-btn').forEach((btn) => { - // Zoom in on clicked gate - btn.addEventListener('click', (evt: Event) => { - const textSvg = btn.querySelector('text'); - const group = btn.parentElement; - if (textSvg == null || group == null) return; + /** + * Add interactive click handlers to circuit HTML elements. + * + * @param container HTML element containing visualized circuit. + * @param circuit Circuit to be visualized. + * + */ + private addGateClickHandlers(container: HTMLElement, circuit: Circuit): void { + this.addClassicalControlHandlers(container); + this.addZoomHandlers(container, circuit); + } - const currValue = textSvg.firstChild?.nodeValue; - const zeroGates = group?.querySelector('.gates-zero'); - const oneGates = group?.querySelector('.gates-one'); - switch (currValue) { - case '?': - textSvg.childNodes[0].nodeValue = '1'; - group.classList.remove('classically-controlled-unknown'); - group.classList.remove('classically-controlled-zero'); - group.classList.add('classically-controlled-one'); - zeroGates?.classList.add('hidden'); - oneGates?.classList.remove('hidden'); - break; - case '1': - textSvg.childNodes[0].nodeValue = '0'; - group.classList.remove('classically-controlled-unknown'); - group.classList.add('classically-controlled-zero'); - group.classList.remove('classically-controlled-one'); - zeroGates?.classList.remove('hidden'); - oneGates?.classList.add('hidden'); - break; - case '0': - textSvg.childNodes[0].nodeValue = '?'; - group.classList.add('classically-controlled-unknown'); - group.classList.remove('classically-controlled-zero'); - group.classList.remove('classically-controlled-one'); - zeroGates?.classList.remove('hidden'); - oneGates?.classList.remove('hidden'); - break; - } - evt.stopPropagation(); - }); - }); - } + /** + * Add interactive click handlers for classically-controlled operations. + * + * @param container HTML element containing visualized circuit. + * + */ + private addClassicalControlHandlers(container: HTMLElement): void { + container.querySelectorAll(".classically-controlled-btn").forEach((btn) => { + // Zoom in on clicked gate + btn.addEventListener("click", (evt: Event) => { + const textSvg = btn.querySelector("text"); + const group = btn.parentElement; + if (textSvg == null || group == null) return; - /** - * Add interactive click handlers for zoom-in/out functionality. - * - * @param container HTML element containing visualized circuit. - * @param circuit Circuit to be visualized. - * - */ - private addZoomHandlers(container: HTMLElement, circuit: Circuit): void { - container.querySelectorAll('.gate .gate-control').forEach((ctrl) => { - // Zoom in on clicked gate - ctrl.addEventListener('click', (ev: Event) => { - const gateId: string | null | undefined = ctrl.parentElement?.getAttribute('data-id'); - if (typeof gateId == 'string') { - if (ctrl.classList.contains('gate-collapse')) { - this.collapseOperation(circuit.operations, gateId); - } else if (ctrl.classList.contains('gate-expand')) { - this.expandOperation(circuit.operations, gateId); - } - this.renderCircuit(container, circuit); + const currValue = textSvg.firstChild?.nodeValue; + const zeroGates = group?.querySelector(".gates-zero"); + const oneGates = group?.querySelector(".gates-one"); + switch (currValue) { + case "?": + textSvg.childNodes[0].nodeValue = "1"; + group.classList.remove("classically-controlled-unknown"); + group.classList.remove("classically-controlled-zero"); + group.classList.add("classically-controlled-one"); + zeroGates?.classList.add("hidden"); + oneGates?.classList.remove("hidden"); + break; + case "1": + textSvg.childNodes[0].nodeValue = "0"; + group.classList.remove("classically-controlled-unknown"); + group.classList.add("classically-controlled-zero"); + group.classList.remove("classically-controlled-one"); + zeroGates?.classList.remove("hidden"); + oneGates?.classList.add("hidden"); + break; + case "0": + textSvg.childNodes[0].nodeValue = "?"; + group.classList.add("classically-controlled-unknown"); + group.classList.remove("classically-controlled-zero"); + group.classList.remove("classically-controlled-one"); + zeroGates?.classList.remove("hidden"); + oneGates?.classList.remove("hidden"); + break; + } + evt.stopPropagation(); + }); + }); + } - ev.stopPropagation(); - } - }); - }); - } + /** + * Add interactive click handlers for zoom-in/out functionality. + * + * @param container HTML element containing visualized circuit. + * @param circuit Circuit to be visualized. + * + */ + private addZoomHandlers(container: HTMLElement, circuit: Circuit): void { + container.querySelectorAll(".gate .gate-control").forEach((ctrl) => { + // Zoom in on clicked gate + ctrl.addEventListener("click", (ev: Event) => { + const gateId: string | null | undefined = + ctrl.parentElement?.getAttribute("data-id"); + if (typeof gateId == "string") { + if (ctrl.classList.contains("gate-collapse")) { + this.collapseOperation(circuit.operations, gateId); + } else if (ctrl.classList.contains("gate-expand")) { + this.expandOperation(circuit.operations, gateId); + } + this.renderCircuit(container, circuit); - /** - * Expand selected operation for zoom-in interaction. - * - * @param operations List of circuit operations. - * @param id ID of operation to expand. - * - */ - private expandOperation(operations: Operation[], id: string): void { - operations.forEach((op) => { - if (op.conditionalRender === ConditionalRender.AsGroup) this.expandOperation(op.children || [], id); - if (op.dataAttributes == null) return op; - const opId: string = op.dataAttributes['id']; - if (opId === id && op.children != null) { - op.conditionalRender = ConditionalRender.AsGroup; - op.dataAttributes['expanded'] = 'true'; - } - }); - } + ev.stopPropagation(); + } + }); + }); + } - /** - * Collapse selected operation for zoom-out interaction. - * - * @param operations List of circuit operations. - * @param id ID of operation to collapse. - * - */ - private collapseOperation(operations: Operation[], parentId: string): void { - operations.forEach((op) => { - if (op.conditionalRender === ConditionalRender.AsGroup) this.collapseOperation(op.children || [], parentId); - if (op.dataAttributes == null) return op; - const opId: string = op.dataAttributes['id']; - // Collapse parent gate and its children - if (opId.startsWith(parentId)) { - op.conditionalRender = ConditionalRender.Always; - delete op.dataAttributes['expanded']; - } - }); - } + /** + * Expand selected operation for zoom-in interaction. + * + * @param operations List of circuit operations. + * @param id ID of operation to expand. + * + */ + private expandOperation(operations: Operation[], id: string): void { + operations.forEach((op) => { + if (op.conditionalRender === ConditionalRender.AsGroup) + this.expandOperation(op.children || [], id); + if (op.dataAttributes == null) return op; + const opId: string = op.dataAttributes["id"]; + if (opId === id && op.children != null) { + op.conditionalRender = ConditionalRender.AsGroup; + op.dataAttributes["expanded"] = "true"; + } + }); + } + + /** + * Collapse selected operation for zoom-out interaction. + * + * @param operations List of circuit operations. + * @param id ID of operation to collapse. + * + */ + private collapseOperation(operations: Operation[], parentId: string): void { + operations.forEach((op) => { + if (op.conditionalRender === ConditionalRender.AsGroup) + this.collapseOperation(op.children || [], parentId); + if (op.dataAttributes == null) return op; + const opId: string = op.dataAttributes["id"]; + // Collapse parent gate and its children + if (opId.startsWith(parentId)) { + op.conditionalRender = ConditionalRender.Always; + delete op.dataAttributes["expanded"]; + } + }); + } } diff --git a/circuit_vis/src/styles.ts b/circuit_vis/src/styles.ts index 491d563eb2..ad22c45b3d 100644 --- a/circuit_vis/src/styles.ts +++ b/circuit_vis/src/styles.ts @@ -5,82 +5,82 @@ * Provides configuration for CSS styles of visualization. */ export interface StyleConfig { - /** Line stroke style. */ - lineStroke?: string; - /** Line width. */ - lineWidth?: number; - /** Text colour. */ - textColour?: string; - /** Single qubit unitary fill colour. */ - unitary?: string; - /** Oplus circle fill colour. */ - oplus?: string; - /** Measurement gate fill colour. */ - measure?: string; - /** Measurement unknown primary colour. */ - classicalUnknown?: string; - /** Measurement zero primary colour. */ - classicalZero?: string; - /** Measurement one primary colour. */ - classicalOne?: string; - /** Measurement zero text colour */ - classicalZeroText?: string; - /** Measurement one text colour */ - classicalOneText?: string; + /** Line stroke style. */ + lineStroke?: string; + /** Line width. */ + lineWidth?: number; + /** Text colour. */ + textColour?: string; + /** Single qubit unitary fill colour. */ + unitary?: string; + /** Oplus circle fill colour. */ + oplus?: string; + /** Measurement gate fill colour. */ + measure?: string; + /** Measurement unknown primary colour. */ + classicalUnknown?: string; + /** Measurement zero primary colour. */ + classicalZero?: string; + /** Measurement one primary colour. */ + classicalOne?: string; + /** Measurement zero text colour */ + classicalZeroText?: string; + /** Measurement one text colour */ + classicalOneText?: string; } const defaultStyle: StyleConfig = { - lineStroke: '#000000', - lineWidth: 1, - textColour: '#000000', - unitary: '#D9F1FA', - oplus: '#FFFFFF', - measure: '#FFDE86', - classicalUnknown: '#E5E5E5', - classicalZero: '#C40000', - classicalOne: '#4059BD', - classicalZeroText: '#FFFFFF', - classicalOneText: '#FFFFFF', + lineStroke: "#000000", + lineWidth: 1, + textColour: "#000000", + unitary: "#D9F1FA", + oplus: "#FFFFFF", + measure: "#FFDE86", + classicalUnknown: "#E5E5E5", + classicalZero: "#C40000", + classicalOne: "#4059BD", + classicalZeroText: "#FFFFFF", + classicalOneText: "#FFFFFF", }; const blackAndWhiteStyle: StyleConfig = { - lineStroke: '#000000', - lineWidth: 1, - textColour: '#000000', - unitary: '#FFFFFF', - oplus: '#FFFFFF', - measure: '#FFFFFF', - classicalUnknown: '#FFFFFF', - classicalZero: '#000000', - classicalOne: '#000000', - classicalZeroText: '#FFFFFF', - classicalOneText: '#FFFFFF', + lineStroke: "#000000", + lineWidth: 1, + textColour: "#000000", + unitary: "#FFFFFF", + oplus: "#FFFFFF", + measure: "#FFFFFF", + classicalUnknown: "#FFFFFF", + classicalZero: "#000000", + classicalOne: "#000000", + classicalZeroText: "#FFFFFF", + classicalOneText: "#FFFFFF", }; const invertedStyle: StyleConfig = { - lineStroke: '#FFFFFF', - lineWidth: 1, - textColour: '#FFFFFF', - unitary: '#000000', - oplus: '#000000', - measure: '#000000', - classicalUnknown: '#000000', - classicalZero: '#FFFFFF', - classicalOne: '#FFFFFF', - classicalZeroText: '#000000', - classicalOneText: '#000000', + lineStroke: "#FFFFFF", + lineWidth: 1, + textColour: "#FFFFFF", + unitary: "#000000", + oplus: "#000000", + measure: "#000000", + classicalUnknown: "#000000", + classicalZero: "#FFFFFF", + classicalOne: "#FFFFFF", + classicalZeroText: "#000000", + classicalOneText: "#000000", }; /** * Set of default styles. */ export const STYLES: { [name: string]: StyleConfig } = { - /** Default style with coloured gates. */ - Default: defaultStyle, - /** Black and white style. */ - BlackAndWhite: blackAndWhiteStyle, - /** Inverted black and white style (for black backgrounds). */ - Inverted: invertedStyle, + /** Default style with coloured gates. */ + Default: defaultStyle, + /** Black and white style. */ + BlackAndWhite: blackAndWhiteStyle, + /** Inverted black and white style (for black backgrounds). */ + Inverted: invertedStyle, }; /** @@ -91,9 +91,9 @@ export const STYLES: { [name: string]: StyleConfig } = { * @returns String containing CSS style script. */ export const style = (customStyle: StyleConfig = {}): string => { - const styleConfig = { ...defaultStyle, ...customStyle }; + const styleConfig = { ...defaultStyle, ...customStyle }; - return `${_defaultGates(styleConfig)} + return `${_defaultGates(styleConfig)} ${_classicallyControlledGates(styleConfig)} ${_expandCollapse}`; }; @@ -138,7 +138,7 @@ const _defaultGates = (styleConfig: StyleConfig): string => ` }`; const _classicallyControlledGates = (styleConfig: StyleConfig): string => { - const gateOutline = ` + const gateOutline = ` .classically-controlled-one .classical-container, .classically-controlled-one .classical-line { stroke: ${styleConfig.classicalOne}; @@ -153,7 +153,7 @@ const _classicallyControlledGates = (styleConfig: StyleConfig): string => { fill: ${styleConfig.classicalZero}; fill-opacity: 0.1; }`; - const controlBtn = ` + const controlBtn = ` .classically-controlled-btn { cursor: pointer; } @@ -167,7 +167,7 @@ const _classicallyControlledGates = (styleConfig: StyleConfig): string => { fill: ${styleConfig.classicalZero}; }`; - const controlBtnText = ` + const controlBtnText = ` .classically-controlled-btn text { dominant-baseline: middle; text-anchor: middle; @@ -184,7 +184,7 @@ const _classicallyControlledGates = (styleConfig: StyleConfig): string => { fill: ${styleConfig.classicalZeroText}; }`; - return ` + return ` .hidden { display: none; } diff --git a/circuit_vis/src/utils.ts b/circuit_vis/src/utils.ts index 6a7e6c7d9f..cf4f9d2f64 100644 --- a/circuit_vis/src/utils.ts +++ b/circuit_vis/src/utils.ts @@ -1,8 +1,13 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { Metadata, GateType } from './metadata'; -import { minGateWidth, labelPadding, labelFontSize, argsFontSize } from './constants'; +import { Metadata, GateType } from "./metadata"; +import { + minGateWidth, + labelPadding, + labelFontSize, + argsFontSize, +} from "./constants"; /** * Generate a UUID using `Math.random`. @@ -12,11 +17,11 @@ import { minGateWidth, labelPadding, labelFontSize, argsFontSize } from './const * @returns UUID string. */ const createUUID = (): string => - 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { - const r = (Math.random() * 16) | 0, - v = c == 'x' ? r : (r & 0x3) | 0x8; - return v.toString(16); - }); + "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) { + const r = (Math.random() * 16) | 0, + v = c == "x" ? r : (r & 0x3) | 0x8; + return v.toString(16); + }); /** * Calculate the width of a gate, given its metadata. @@ -25,20 +30,26 @@ const createUUID = (): string => * * @returns Width of given gate (in pixels). */ -const getGateWidth = ({ type, label, displayArgs, width }: Metadata): number => { - if (width > 0) return width; +const getGateWidth = ({ + type, + label, + displayArgs, + width, +}: Metadata): number => { + if (width > 0) return width; - switch (type) { - case GateType.Measure: - case GateType.Cnot: - case GateType.Swap: - return minGateWidth; - default: - const labelWidth = _getStringWidth(label); - const argsWidth = displayArgs != null ? _getStringWidth(displayArgs, argsFontSize) : 0; - const textWidth = Math.max(labelWidth, argsWidth) + labelPadding * 2; - return Math.max(minGateWidth, textWidth); - } + switch (type) { + case GateType.Measure: + case GateType.Cnot: + case GateType.Swap: + return minGateWidth; + default: + const labelWidth = _getStringWidth(label); + const argsWidth = + displayArgs != null ? _getStringWidth(displayArgs, argsFontSize) : 0; + const textWidth = Math.max(labelWidth, argsWidth) + labelPadding * 2; + return Math.max(minGateWidth, textWidth); + } }; /** @@ -49,14 +60,17 @@ const getGateWidth = ({ type, label, displayArgs, width }: Metadata): number => * * @returns Pixel width of given string. */ -const _getStringWidth = (text: string, fontSize: number = labelFontSize): number => { - const canvas: HTMLCanvasElement = document.createElement('canvas'); - const context: CanvasRenderingContext2D | null = canvas.getContext('2d'); - if (context == null) throw new Error('Null canvas'); +const _getStringWidth = ( + text: string, + fontSize: number = labelFontSize, +): number => { + const canvas: HTMLCanvasElement = document.createElement("canvas"); + const context: CanvasRenderingContext2D | null = canvas.getContext("2d"); + if (context == null) throw new Error("Null canvas"); - context.font = `${fontSize}px Arial`; - const metrics: TextMetrics = context.measureText(text); - return metrics.width; + context.font = `${fontSize}px Arial`; + const metrics: TextMetrics = context.measureText(text); + return metrics.width; }; export { createUUID, getGateWidth, _getStringWidth }; diff --git a/circuit_vis/tsconfig.json b/circuit_vis/tsconfig.json index 47f4409706..85efcd2f95 100644 --- a/circuit_vis/tsconfig.json +++ b/circuit_vis/tsconfig.json @@ -1,17 +1,12 @@ { - "compilerOptions": { - "target": "es5", - "module": "commonjs", - "lib": [ - "DOM", - "ES2019", - ], - "declaration": true, - "strict": true, - "outDir": "lib", - "skipLibCheck": true - }, - "include": [ - "src/**/*" - ] + "compilerOptions": { + "target": "es5", + "module": "commonjs", + "lib": ["DOM", "ES2019"], + "declaration": true, + "strict": true, + "outDir": "lib", + "skipLibCheck": true + }, + "include": ["src/**/*"] } diff --git a/circuit_vis/webpack.config.js b/circuit_vis/webpack.config.js index d712e5ca04..eb57c1e22c 100644 --- a/circuit_vis/webpack.config.js +++ b/circuit_vis/webpack.config.js @@ -1,71 +1,71 @@ -const path = require('path'); -const TerserPlugin = require('terser-webpack-plugin'); +const path = require("path"); +const TerserPlugin = require("terser-webpack-plugin"); const PATHS = { - entryPoint: path.resolve(__dirname, 'src/index.ts'), - bundles: path.resolve(__dirname, 'dist'), + entryPoint: path.resolve(__dirname, "src/index.ts"), + bundles: path.resolve(__dirname, "dist"), }; const config = { - // Enables production mode built-in optimizations - mode: 'production', - // These are the entry point of our library. We tell webpack to use - // the name we assign later, when creating the bundle. We also use - // the name to filter the second entry point for applying code - // minification via UglifyJS - entry: { - qviz: [PATHS.entryPoint], - 'qviz.min': [PATHS.entryPoint], - }, - // The output defines how and where we want the bundles. The special - // value `[name]` in `filename` tell Webpack to use the name we defined above. - // The bundled script will be available as a global variable `qviz`. - output: { - path: PATHS.bundles, - filename: '[name].js', - library: 'qviz', - libraryTarget: 'umd', - }, - // Add resolve for `tsx` and `ts` files, otherwise Webpack would - // only look for common JavaScript file extension (.js) - resolve: { - extensions: ['.ts', '.tsx', '.js'], - }, - // Activate source maps for the bundles in order to preserve the original - // source when the user debugs the application - devtool: 'source-map', - optimization: { - // Apply minification only on the second bundle by - // using a RegEx on the name, which must end with `.min.js` - minimize: true, - minimizer: [ - new TerserPlugin({ - sourceMap: true, - include: /\.min\.js$/, - }), - ], - }, - module: { - // Webpack doesn't understand TypeScript files and a loader is needed. - // `node_modules` folder is excluded in order to prevent problems with - // the library dependencies, as well as `__tests__` folders that - // contain the tests for the library - rules: [ - { - test: /\.tsx?$/, - exclude: /node_modules/, - use: [ - { - loader: 'ts-loader', - options: { - // Speeds up compilation and does not build *.d.ts files - transpileOnly: true, - }, - }, - ], + // Enables production mode built-in optimizations + mode: "production", + // These are the entry point of our library. We tell webpack to use + // the name we assign later, when creating the bundle. We also use + // the name to filter the second entry point for applying code + // minification via UglifyJS + entry: { + qviz: [PATHS.entryPoint], + "qviz.min": [PATHS.entryPoint], + }, + // The output defines how and where we want the bundles. The special + // value `[name]` in `filename` tell Webpack to use the name we defined above. + // The bundled script will be available as a global variable `qviz`. + output: { + path: PATHS.bundles, + filename: "[name].js", + library: "qviz", + libraryTarget: "umd", + }, + // Add resolve for `tsx` and `ts` files, otherwise Webpack would + // only look for common JavaScript file extension (.js) + resolve: { + extensions: [".ts", ".tsx", ".js"], + }, + // Activate source maps for the bundles in order to preserve the original + // source when the user debugs the application + devtool: "source-map", + optimization: { + // Apply minification only on the second bundle by + // using a RegEx on the name, which must end with `.min.js` + minimize: true, + minimizer: [ + new TerserPlugin({ + sourceMap: true, + include: /\.min\.js$/, + }), + ], + }, + module: { + // Webpack doesn't understand TypeScript files and a loader is needed. + // `node_modules` folder is excluded in order to prevent problems with + // the library dependencies, as well as `__tests__` folders that + // contain the tests for the library + rules: [ + { + test: /\.tsx?$/, + exclude: /node_modules/, + use: [ + { + loader: "ts-loader", + options: { + // Speeds up compilation and does not build *.d.ts files + transpileOnly: true, }, + }, ], - }, + }, + ], + }, }; module.exports = config; From 818a9130940b4061156de31602230f4fc442c23d Mon Sep 17 00:00:00 2001 From: Mine Starks Date: Thu, 9 May 2024 11:20:40 -0700 Subject: [PATCH 3/5] (circuits) incorporate circuit_vis into build --- build.py | 46 +- circuit_vis/.eslintignore | 5 - circuit_vis/.eslintrc.cjs | 23 - circuit_vis/package.json | 6 - circuit_vis/src/formatters/gateFormatter.ts | 16 +- circuit_vis/src/process.ts | 29 +- circuit_vis/src/sqore.ts | 2 + circuit_vis/src/utils.ts | 3 +- eslint.config.mjs | 5 + package-lock.json | 11125 ++++++++++++++---- package.json | 4 +- 11 files changed, 8648 insertions(+), 2616 deletions(-) delete mode 100644 circuit_vis/.eslintignore delete mode 100644 circuit_vis/.eslintrc.cjs diff --git a/build.py b/build.py index 0ee53ec667..ec9a6829fc 100755 --- a/build.py +++ b/build.py @@ -117,6 +117,7 @@ wasm_bld = os.path.join(root_dir, "target", "wasm32", build_type) samples_src = os.path.join(root_dir, "samples") npm_src = os.path.join(root_dir, "npm", "qsharp") +circuit_vis_src = os.path.join(root_dir, "circuit_vis") play_src = os.path.join(root_dir, "playground") pip_src = os.path.join(root_dir, "pip") widgets_src = os.path.join(root_dir, "widgets") @@ -357,23 +358,6 @@ def run_ci_historic_benchmark(): step_end() -if build_widgets: - step_start("Building the Python widgets") - - widgets_build_args = [ - sys.executable, - "-m", - "pip", - "wheel", - "--no-deps", - "--wheel-dir", - wheels_dir, - widgets_src, - ] - subprocess.run(widgets_build_args, check=True, text=True, cwd=widgets_src) - - step_end() - if build_wasm: step_start("Building the wasm crate") # wasm-pack can't build for web and node in the same build, so need to run twice. @@ -394,6 +378,17 @@ def run_ci_historic_benchmark(): ) step_end() +if build_npm: + step_start("Building the circuit_vis package") + + npm_args = [npm_cmd, "install"] + subprocess.run(npm_args, check=True, text=True, cwd=circuit_vis_src) + + npm_args = [npm_cmd, "run", "build:prod"] + subprocess.run(npm_args, check=True, text=True, cwd=circuit_vis_src) + + step_end() + if build_npm: step_start("Building the npm package") # Copy the wasm build files over for web and node targets @@ -422,6 +417,23 @@ def run_ci_historic_benchmark(): subprocess.run(npm_test_args, check=True, text=True, cwd=npm_src) step_end() +if build_widgets: + step_start("Building the Python widgets") + + widgets_build_args = [ + sys.executable, + "-m", + "pip", + "wheel", + "--no-deps", + "--wheel-dir", + wheels_dir, + widgets_src, + ] + subprocess.run(widgets_build_args, check=True, text=True, cwd=widgets_src) + + step_end() + if build_play: step_start("Building the playground") play_args = [npm_cmd, "run", "build"] diff --git a/circuit_vis/.eslintignore b/circuit_vis/.eslintignore deleted file mode 100644 index 823d7d2d02..0000000000 --- a/circuit_vis/.eslintignore +++ /dev/null @@ -1,5 +0,0 @@ -coverage/ -dist/ -lib/ -node_modules/ -*.config.js diff --git a/circuit_vis/.eslintrc.cjs b/circuit_vis/.eslintrc.cjs deleted file mode 100644 index 6ec2ace09b..0000000000 --- a/circuit_vis/.eslintrc.cjs +++ /dev/null @@ -1,23 +0,0 @@ -module.exports = { - parser: "@typescript-eslint/parser", // Specifies the ESLint parser - parserOptions: { - ecmaVersion: 2019, // Allows for the parsing of modern ECMAScript features - sourceType: "module", // Allows for the use of imports - }, - extends: [ - "plugin:@typescript-eslint/recommended", // Uses the recommended rules from the @typescript-eslint/eslint-plugin - "prettier/@typescript-eslint", // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier - "plugin:prettier/recommended", // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. - ], - plugins: ["jest"], - rules: { - // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs - // e.g. "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "_" }], - "jest/no-disabled-tests": "warn", - "jest/no-focused-tests": "error", - "jest/no-identical-title": "error", - "jest/prefer-to-have-length": "warn", - "jest/valid-expect": "error", - }, -}; diff --git a/circuit_vis/package.json b/circuit_vis/package.json index fb95e59ebf..2b14f03b1b 100644 --- a/circuit_vis/package.json +++ b/circuit_vis/package.json @@ -33,13 +33,7 @@ "devDependencies": { "@types/jest": "^26.0.4", "@types/prettier": "2.6.0", - "@typescript-eslint/eslint-plugin": "^3.9.0", - "@typescript-eslint/parser": "^3.9.0", "canvas": "^2.6.1", - "eslint": "^7.6.0", - "eslint-config-prettier": "^6.11.0", - "eslint-plugin-jest": "^23.20.0", - "eslint-plugin-prettier": "^3.1.4", "jest": "^26.6.3", "prettier": "2.6.0", "terser-webpack-plugin": "^4.1.0", diff --git a/circuit_vis/src/formatters/gateFormatter.ts b/circuit_vis/src/formatters/gateFormatter.ts index fda0932623..f4be3626df 100644 --- a/circuit_vis/src/formatters/gateFormatter.ts +++ b/circuit_vis/src/formatters/gateFormatter.ts @@ -167,7 +167,7 @@ const _gatePosition = ( let x1: number, y1: number, x2: number, y2: number; switch (type) { - case GateType.Group: + case GateType.Group: { const padding = groupBoxPadding - nestedDepth * nestedGroupPadding; x1 = x - 2 * padding; @@ -176,6 +176,7 @@ const _gatePosition = ( y2 = maxY + +gateHeight / 2 + padding - (minY - gateHeight / 2 - padding); return [x1, y1, x2, y2]; + } default: x1 = x - width / 2; @@ -321,6 +322,7 @@ const _swap = (metadata: Metadata, nestedDepth: number): SVGElement => { * * @returns SVG representation of X gate. */ +// eslint-disable-next-line @typescript-eslint/no-unused-vars const _x = (metadata: Metadata, _: number): SVGElement => { const { x, targetsY } = metadata; const ys = targetsY.flatMap((y) => y as number[]); @@ -375,11 +377,13 @@ const _controlledGate = ( (targetsY as number[]).forEach((y) => targetGateSvgs.push(_cross(x, y))); break; case GateType.ControlledUnitary: - const groupedTargetsY: number[][] = targetsY as number[][]; - targetGateSvgs.push( - _unitary(label, x, groupedTargetsY, width, displayArgs, false), - ); - targetsY = targetsY.flat(); + { + const groupedTargetsY: number[][] = targetsY as number[][]; + targetGateSvgs.push( + _unitary(label, x, groupedTargetsY, width, displayArgs, false), + ); + targetsY = targetsY.flat(); + } break; default: throw new Error(`ERROR: Unrecognized gate: ${label} of type ${type}`); diff --git a/circuit_vis/src/process.ts b/circuit_vis/src/process.ts index d896cb590e..f18d7be1cf 100644 --- a/circuit_vis/src/process.ts +++ b/circuit_vis/src/process.ts @@ -56,6 +56,7 @@ const processOperations = ( regOps.map((opIdx, col) => { let op: Operation | null = null; + // eslint-disable-next-line no-prototype-builtins if (opIdx != null && !visited.hasOwnProperty(opIdx)) { op = operations[opIdx]; visited[opIdx] = true; @@ -72,7 +73,9 @@ const processOperations = ( // Get y coordinates of classical registers in the same column as this operation const classicalRegY: number[] = classicalRegs + // eslint-disable-next-line @typescript-eslint/no-unused-vars .filter(([regCol, _]) => regCol <= col) + // eslint-disable-next-line @typescript-eslint/no-unused-vars .map(([_, reg]) => { if (reg.cId == null) throw new Error("Could not find cId for classical register."); @@ -362,7 +365,7 @@ const _opToMetadata = ( */ const _getRegY = (reg: Register, registers: RegisterMap): number => { const { type, qId, cId } = reg; - if (!registers.hasOwnProperty(qId)) + if (!Object.prototype.hasOwnProperty.call(registers, qId)) throw new Error(`ERROR: Qubit register with ID ${qId} not found.`); const { y, children } = registers[qId]; switch (type) { @@ -478,17 +481,19 @@ const _fillMetadataX = ( switch (metadata.type) { case GateType.ClassicalControlled: case GateType.Group: - // Subtract startX offset from nested gates and add offset and padding - let offset: number = x - startX + groupBoxPadding; - if (metadata.type === GateType.ClassicalControlled) - offset += controlBtnOffset; - - // Offset each x coord in children gates - _offsetChildrenX(metadata.children, offset); - - // We don't use the centre x coord because we only care about the rightmost x for - // rendering the box around the group of nested gates - metadata.x = x; + { + // Subtract startX offset from nested gates and add offset and padding + let offset: number = x - startX + groupBoxPadding; + if (metadata.type === GateType.ClassicalControlled) + offset += controlBtnOffset; + + // Offset each x coord in children gates + _offsetChildrenX(metadata.children, offset); + + // We don't use the centre x coord because we only care about the rightmost x for + // rendering the box around the group of nested gates + metadata.x = x; + } break; default: diff --git a/circuit_vis/src/sqore.ts b/circuit_vis/src/sqore.ts index f3899739a5..2c3263265f 100644 --- a/circuit_vis/src/sqore.ts +++ b/circuit_vis/src/sqore.ts @@ -75,6 +75,7 @@ export class Sqore { if ( circuit.operations.length == 1 && circuit.operations[0].dataAttributes != null && + // eslint-disable-next-line no-prototype-builtins circuit.operations[0].dataAttributes.hasOwnProperty("id") ) { const id: string = circuit.operations[0].dataAttributes["id"]; @@ -94,6 +95,7 @@ export class Sqore { private getStyle(style: StyleConfig | string = {}): StyleConfig { if (typeof style === "string" || style instanceof String) { const styleName: string = style as string; + // eslint-disable-next-line no-prototype-builtins if (!STYLES.hasOwnProperty(styleName)) { console.error(`No style ${styleName} found in STYLES.`); return {}; diff --git a/circuit_vis/src/utils.ts b/circuit_vis/src/utils.ts index cf4f9d2f64..8ce9f9d4eb 100644 --- a/circuit_vis/src/utils.ts +++ b/circuit_vis/src/utils.ts @@ -43,12 +43,13 @@ const getGateWidth = ({ case GateType.Cnot: case GateType.Swap: return minGateWidth; - default: + default: { const labelWidth = _getStringWidth(label); const argsWidth = displayArgs != null ? _getStringWidth(displayArgs, argsFontSize) : 0; const textWidth = Math.max(labelWidth, argsWidth) + labelPadding * 2; return Math.max(minGateWidth, textWidth); + } } }; diff --git a/eslint.config.mjs b/eslint.config.mjs index 96c46336f9..8cb84632ef 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -12,6 +12,11 @@ export default tseslint.config( }, { ignores: [ + "circuit_vis/example/", + "circuit_vis/lib/", + "circuit_vis/coverage/", + "circuit_vis/dist/", + "circuit_vis/*.config.js", "target/", "playground/public/", "npm/qsharp/dist/", diff --git a/package-lock.json b/package-lock.json index 49c221caea..00a9dcd592 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,12 +9,12 @@ "workspaces": [ "./npm/qsharp", "./playground", - "./vscode" + "./vscode", + "./circuit_vis" ], "devDependencies": { "@anywidget/types": "^0.1.4", "@eslint/js": "^9.9.1", - "@microsoft/quantum-viz.js": "^1.0.5", "@parcel/watcher": "^2.4.1", "@types/chai": "^4.3.8", "@types/markdown-it": "^14.1.1", @@ -50,19 +50,103 @@ "node": ">=18.17.1" } }, + "circuit_vis": { + "name": "@microsoft/quantum-viz.js", + "version": "1.0.6", + "license": "MIT", + "devDependencies": { + "@types/jest": "^26.0.4", + "@types/prettier": "2.6.0", + "canvas": "^2.6.1", + "jest": "^26.6.3", + "prettier": "2.6.0", + "terser-webpack-plugin": "^4.1.0", + "ts-jest": "^26.1.2", + "ts-loader": "^8.0.2", + "typescript": "^4.9.4", + "webpack": "^5.75.0", + "webpack-cli": "^5.0.1" + } + }, + "circuit_vis/node_modules/prettier": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.0.tgz", + "integrity": "sha512-m2FgJibYrBGGgQXNzfd0PuDGShJgRavjUoRCw1mZERIWVSXF0iLzLm+aOqTAbLnC3n6JzUhAA8uZnFVghHJ86A==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "circuit_vis/node_modules/ts-jest": { + "version": "26.5.6", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.6.tgz", + "integrity": "sha512-rua+rCP8DxpA8b4DQD/6X2HQS8Zy/xzViVYfEs2OQu68tkCuKLV0Md8pmX55+W24uRIyAsf/BajRfxOs+R2MKA==", + "dev": true, + "dependencies": { + "bs-logger": "0.x", + "buffer-from": "1.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^26.1.0", + "json5": "2.x", + "lodash": "4.x", + "make-error": "1.x", + "mkdirp": "1.x", + "semver": "7.x", + "yargs-parser": "20.x" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "jest": ">=26 <27", + "typescript": ">=3.8 <5.0" + } + }, + "circuit_vis/node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/@aashutoshrathi/word-wrap": { "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@anywidget/types": { "version": "0.1.7", - "resolved": "https://registry.npmjs.org/@anywidget/types/-/types-0.1.7.tgz", - "integrity": "sha512-S/ZloESHBpaN88Npnggc1Ykk+jI2lahID56qZPwAM4HGCWyWdt7QcTKxfBYbGW+G8wwCZW+hv0bzOAkuwMDEmg==", "dev": true, "dependencies": { "@jupyter-widgets/base": "^6.0.7" @@ -70,9 +154,8 @@ }, "node_modules/@azure/abort-controller": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.1.tgz", - "integrity": "sha512-NhzeNm5zu2fPlwGXPUjzsRCRuPx5demaZyNcyNYJDqpa/Sbxzvo/RYt9IwUaAOnDW5+r7J9UOE6f22TQnb9nhQ==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^2.6.2" }, @@ -82,9 +165,8 @@ }, "node_modules/@azure/core-auth": { "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.7.1.tgz", - "integrity": "sha512-dyeQwvgthqs/SlPVQbZQetpslXceHd4i5a7M/7z/lGEAVwnSluabnQOjF2/dk/hhWgMISusv1Ytp4mQ8JNy62A==", "dev": true, + "license": "MIT", "dependencies": { "@azure/abort-controller": "^2.0.0", "@azure/core-util": "^1.1.0", @@ -96,9 +178,8 @@ }, "node_modules/@azure/core-rest-pipeline": { "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.10.1.tgz", - "integrity": "sha512-Kji9k6TOFRDB5ZMTw8qUf2IJ+CeJtsuMdAHox9eqpTf1cefiNMpzrfnF6sINEBZJsaVaWgQ0o48B6kcUH68niA==", "dev": true, + "license": "MIT", "dependencies": { "@azure/abort-controller": "^1.0.0", "@azure/core-auth": "^1.4.0", @@ -117,9 +198,8 @@ }, "node_modules/@azure/core-rest-pipeline/node_modules/@azure/abort-controller": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz", - "integrity": "sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^2.2.0" }, @@ -129,9 +209,8 @@ }, "node_modules/@azure/core-rest-pipeline/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, + "license": "MIT", "dependencies": { "debug": "4" }, @@ -141,9 +220,8 @@ }, "node_modules/@azure/core-rest-pipeline/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, + "license": "MIT", "dependencies": { "@tootallnate/once": "2", "agent-base": "6", @@ -155,9 +233,8 @@ }, "node_modules/@azure/core-rest-pipeline/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==", "dev": true, + "license": "MIT", "dependencies": { "agent-base": "6", "debug": "4" @@ -168,9 +245,8 @@ }, "node_modules/@azure/core-tracing": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.1.1.tgz", - "integrity": "sha512-qPbYhN1pE5XQ2jPKIHP33x8l3oBu1UqIWnYqZZ3OYnYjzY0xqIHjn49C+ptsPD9yC7uyWI9Zm7iZUZLs2R4DhQ==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^2.6.2" }, @@ -180,9 +256,8 @@ }, "node_modules/@azure/core-util": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.2.0.tgz", - "integrity": "sha512-ffGIw+Qs8bNKNLxz5UPkz4/VBM/EZY07mPve1ZYFqYUdPwFqRj0RPk0U7LZMOfT7GCck9YjuT1Rfp1PApNl1ng==", "dev": true, + "license": "MIT", "dependencies": { "@azure/abort-controller": "^1.0.0", "tslib": "^2.2.0" @@ -193,9 +268,8 @@ }, "node_modules/@azure/core-util/node_modules/@azure/abort-controller": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz", - "integrity": "sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^2.2.0" }, @@ -205,9 +279,8 @@ }, "node_modules/@azure/logger": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.1.1.tgz", - "integrity": "sha512-/+4TtokaGgC+MnThdf6HyIH9Wrjp+CnCn3Nx3ggevN7FFjjNyjqg0yLlc2i9S+Z2uAzI8GYOo35Nzb1MhQ89MA==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^2.6.2" }, @@ -217,9 +290,8 @@ }, "node_modules/@azure/opentelemetry-instrumentation-azure-sdk": { "version": "1.0.0-beta.5", - "resolved": "https://registry.npmjs.org/@azure/opentelemetry-instrumentation-azure-sdk/-/opentelemetry-instrumentation-azure-sdk-1.0.0-beta.5.tgz", - "integrity": "sha512-fsUarKQDvjhmBO4nIfaZkfNSApm1hZBzcvpNbSrXdcUBxu7lRvKsV5DnwszX7cnhLyVOW9yl1uigtRQ1yDANjA==", "dev": true, + "license": "MIT", "dependencies": { "@azure/core-tracing": "^1.0.0", "@azure/logger": "^1.0.0", @@ -232,385 +304,610 @@ "node": ">=14.0.0" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", - "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", - "cpu": [ - "ppc64" - ], + "node_modules/@babel/code-frame": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz", + "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", "dev": true, - "optional": true, - "os": [ - "aix" - ], + "dependencies": { + "@babel/highlight": "^7.25.7", + "picocolors": "^1.0.0" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", - "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", - "cpu": [ - "arm" - ], + "node_modules/@babel/compat-data": { + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.8.tgz", + "integrity": "sha512-ZsysZyXY4Tlx+Q53XdnOFmqwfB9QDTHYxaZYajWRoBLuLEAwI2UIbtxOjWh/cFaa9IKUlcB+DDuoskLuKu56JA==", "dev": true, - "optional": true, - "os": [ - "android" - ], "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", - "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/core": { + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.8.tgz", + "integrity": "sha512-Oixnb+DzmRT30qu9d3tJSQkxuygWm32DFykT4bRoORPa9hZ/L4KhVB/XiRm6KG+roIEM7DBQlmg27kw2HZkdZg==", "dev": true, - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.25.7", + "@babel/generator": "^7.25.7", + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helpers": "^7.25.7", + "@babel/parser": "^7.25.8", + "@babel/template": "^7.25.7", + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.8", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", - "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", - "cpu": [ - "x64" - ], + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", - "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/generator": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.7.tgz", + "integrity": "sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "@babel/types": "^7.25.7", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", - "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", - "cpu": [ - "x64" - ], + "node_modules/@babel/helper-compilation-targets": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.7.tgz", + "integrity": "sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "@babel/compat-data": "^7.25.7", + "@babel/helper-validator-option": "^7.25.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", - "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/helper-compilation-targets/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, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" + "dependencies": { + "yallist": "^3.0.2" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", - "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", - "cpu": [ - "x64" - ], + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", - "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", - "cpu": [ - "arm" - ], + "node_modules/@babel/helper-compilation-targets/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/@babel/helper-module-imports": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.7.tgz", + "integrity": "sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", - "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/helper-module-transforms": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.7.tgz", + "integrity": "sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-module-imports": "^7.25.7", + "@babel/helper-simple-access": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "@babel/traverse": "^7.25.7" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", - "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", - "cpu": [ - "ia32" - ], + "node_modules/@babel/helper-plugin-utils": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.7.tgz", + "integrity": "sha512-eaPZai0PiqCi09pPs3pAFfl/zYgGaE6IdXtYvmf0qlcDTd3WCtO7JWCcRd64e0EQrcYgiHibEZnOGsSY4QSgaw==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", - "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", - "cpu": [ - "loong64" - ], + "node_modules/@babel/helper-simple-access": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.7.tgz", + "integrity": "sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", - "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", - "cpu": [ - "mips64el" - ], + "node_modules/@babel/helper-string-parser": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", + "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", - "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", - "cpu": [ - "ppc64" - ], + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", + "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", - "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", - "cpu": [ - "riscv64" - ], + "node_modules/@babel/helper-validator-option": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.7.tgz", + "integrity": "sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", - "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", - "cpu": [ - "s390x" - ], + "node_modules/@babel/helpers": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.7.tgz", + "integrity": "sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/template": "^7.25.7", + "@babel/types": "^7.25.7" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", - "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", - "cpu": [ - "x64" - ], + "node_modules/@babel/highlight": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz", + "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", - "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", - "cpu": [ - "x64" - ], + "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, - "optional": true, - "os": [ - "netbsd" - ], + "dependencies": { + "color-convert": "^1.9.0" + }, "engines": { - "node": ">=18" + "node": ">=4" } }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", - "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", - "cpu": [ - "arm64" - ], + "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, - "optional": true, - "os": [ - "openbsd" - ], + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, "engines": { - "node": ">=18" + "node": ">=4" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", - "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", - "cpu": [ - "x64" - ], + "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, - "optional": true, - "os": [ - "openbsd" - ], "engines": { - "node": ">=18" + "node": ">=0.8.0" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", - "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", - "cpu": [ - "x64" - ], + "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, - "optional": true, - "os": [ - "sunos" - ], "engines": { - "node": ">=18" + "node": ">=4" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", - "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", - "cpu": [ - "arm64" - ], + "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, - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "has-flag": "^3.0.0" + }, "engines": { - "node": ">=18" + "node": ">=4" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", - "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", - "cpu": [ - "ia32" - ], + "node_modules/@babel/parser": { + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.8.tgz", + "integrity": "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==", "dev": true, - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@babel/types": "^7.25.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, "engines": { - "node": ">=18" + "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, + "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, + "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-import-attributes": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.7.tgz", + "integrity": "sha512-AqVo+dguCgmpi/3mYBdu9lkngOBlQ2w2vnNpa6gfiCxQZLzV4ZbhsXitJ2Yblkoe1VQwtHSaNmIaGll/26YWRw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "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, + "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-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/template": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.7.tgz", + "integrity": "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.7.tgz", + "integrity": "sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.25.7", + "@babel/generator": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/template": "^7.25.7", + "@babel/types": "^7.25.7", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/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/@babel/types": { + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.8.tgz", + "integrity": "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.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 + }, + "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/@esbuild/win32-x64": { + "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/@esbuild/linux-x64": { "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", - "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ - "win32" + "linux" ], "engines": { "node": ">=18" @@ -618,9 +915,8 @@ }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, + "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.3.0" }, @@ -633,18 +929,16 @@ }, "node_modules/@eslint-community/regexpp": { "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -665,9 +959,8 @@ }, "node_modules/@eslint/eslintrc/node_modules/ajv": { "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -681,9 +974,8 @@ }, "node_modules/@eslint/eslintrc/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, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -691,9 +983,8 @@ }, "node_modules/@eslint/eslintrc/node_modules/globals": { "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -703,15 +994,13 @@ }, "node_modules/@eslint/eslintrc/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 + "dev": true, + "license": "MIT" }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -721,19 +1010,22 @@ }, "node_modules/@eslint/js": { "version": "9.9.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.1.tgz", - "integrity": "sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "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.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", "dev": true, + "license": "Apache-2.0", "dependencies": { "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", @@ -745,9 +1037,8 @@ }, "node_modules/@humanwhocodes/config-array/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, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -755,9 +1046,8 @@ }, "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -767,9 +1057,8 @@ }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -780,16 +1069,13 @@ }, "node_modules/@humanwhocodes/object-schema": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@humanwhocodes/retry": { "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.2.4.tgz", - "integrity": "sha512-Ttl/jHpxfS3st5sxwICYfk4pOH0WrLI1SpW283GgQL7sCWU7EHIOhX4b4fkIxr3tkfzwg8+FNojtzsIEE7Ecgg==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=18.18" }, @@ -800,9 +1086,8 @@ }, "node_modules/@isaacs/cliui": { "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -817,9 +1102,8 @@ }, "node_modules/@isaacs/cliui/node_modules/ansi-regex": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -829,9 +1113,8 @@ }, "node_modules/@isaacs/cliui/node_modules/ansi-styles": { "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -841,15 +1124,13 @@ }, "node_modules/@isaacs/cliui/node_modules/emoji-regex": { "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@isaacs/cliui/node_modules/string-width": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, + "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -864,9 +1145,8 @@ }, "node_modules/@isaacs/cliui/node_modules/strip-ansi": { "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -879,9 +1159,8 @@ }, "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -894,65 +1173,505 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@jupyter-widgets/base": { - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/@jupyter-widgets/base/-/base-6.0.7.tgz", - "integrity": "sha512-a4VoUtL+90mGH6VE6m78D2J9aNy9Q1JrPP91HAQTXBysVpCLTtq0Ie8EupN5Su7V8eFwl/wz91J2m0p4jY4h0g==", + "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": { - "@jupyterlab/services": "^6.0.0 || ^7.0.0", - "@lumino/coreutils": "^1.11.1 || ^2.1", - "@lumino/messaging": "^1.10.1 || ^2.1", - "@lumino/widgets": "^1.30.0 || ^2.1", - "@types/backbone": "1.4.14", - "@types/lodash": "^4.14.134", - "backbone": "1.4.0", - "jquery": "^3.1.1", - "lodash": "^4.17.4" + "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/@jupyter/ydoc": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@jupyter/ydoc/-/ydoc-1.1.1.tgz", - "integrity": "sha512-fXx9CbUwUlXBsJo83tBQL3T0MgWT4YYz2ozcSFj0ymZSohAnI1uo7N9CPpVe4/nmc9uG1lFdlXC4XQBevi2jSA==", + "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, "dependencies": { - "@jupyterlab/nbformat": "^3.0.0 || ^4.0.0-alpha.21 || ^4.0.0", - "@lumino/coreutils": "^1.11.0 || ^2.0.0", - "@lumino/disposable": "^1.10.0 || ^2.0.0", - "@lumino/signaling": "^1.10.0 || ^2.0.0", - "y-protocols": "^1.0.5", - "yjs": "^13.5.40" + "sprintf-js": "~1.0.2" } }, - "node_modules/@jupyterlab/coreutils": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/@jupyterlab/coreutils/-/coreutils-6.1.5.tgz", - "integrity": "sha512-J99Rs2YNNl1QgVwq4UtN4CInccjvjk6jVWYlTgmN5XoCaWkucfLO9ZKbbGIYahh2liStHts6eOiAb9ZrouE0zA==", + "node_modules/@istanbuljs/load-nyc-config/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, - "dependencies": { - "@lumino/coreutils": "^2.1.2", - "@lumino/disposable": "^2.1.2", - "@lumino/signaling": "^2.1.2", - "minimist": "~1.2.0", - "path-browserify": "^1.0.0", - "url-parse": "~1.5.4" + "engines": { + "node": ">=6" + } + }, + "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/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/@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/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, + "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": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.6.2.tgz", + "integrity": "sha512-IY1R2i2aLsLr7Id3S6p2BA82GNWryt4oSvEXLAKc+L2zdi89dSkE8xC1C+0kpATG4JhBJREnQOH7/zmccM2B0g==", + "dev": true, + "dependencies": { + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^26.6.2", + "jest-util": "^26.6.2", + "slash": "^3.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/@jest/core": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-26.6.3.tgz", + "integrity": "sha512-xvV1kKbhfUqFVuZ8Cyo+JPpipAHHAV3kcDBftiduK8EICXmTFddryy3P7NfZt8Pv37rA9nEJBKCCkglCPt/Xjw==", + "dev": true, + "dependencies": { + "@jest/console": "^26.6.2", + "@jest/reporters": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/transform": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.4", + "jest-changed-files": "^26.6.2", + "jest-config": "^26.6.3", + "jest-haste-map": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-regex-util": "^26.0.0", + "jest-resolve": "^26.6.2", + "jest-resolve-dependencies": "^26.6.3", + "jest-runner": "^26.6.3", + "jest-runtime": "^26.6.3", + "jest-snapshot": "^26.6.2", + "jest-util": "^26.6.2", + "jest-validate": "^26.6.2", + "jest-watcher": "^26.6.2", + "micromatch": "^4.0.2", + "p-each-series": "^2.1.0", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/@jest/environment": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.6.2.tgz", + "integrity": "sha512-nFy+fHl28zUrRsCeMB61VDThV1pVTtlEokBRgqPrcT1JNq4yRNIyTHfyht6PqtUvY9IsuLGTrbG8kPXjSZIZwA==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "jest-mock": "^26.6.2" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/@jest/fake-timers": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.6.2.tgz", + "integrity": "sha512-14Uleatt7jdzefLPYM3KLcnUl1ZNikaKq34enpb5XG9i81JpppDb5muZvonvKyrl7ftEHkKS5L5/eB/kxJ+bvA==", + "dev": true, + "dependencies": { + "@jest/types": "^26.6.2", + "@sinonjs/fake-timers": "^6.0.1", + "@types/node": "*", + "jest-message-util": "^26.6.2", + "jest-mock": "^26.6.2", + "jest-util": "^26.6.2" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/@jest/globals": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.6.2.tgz", + "integrity": "sha512-85Ltnm7HlB/KesBUuALwQ68YTU72w9H2xW9FjZ1eL1U3lhtefjjl5c2MiUbpXt/i6LaPRvoOFJ22yCBSfQ0JIA==", + "dev": true, + "dependencies": { + "@jest/environment": "^26.6.2", + "@jest/types": "^26.6.2", + "expect": "^26.6.2" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/@jest/reporters": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-26.6.2.tgz", + "integrity": "sha512-h2bW53APG4HvkOnVMo8q3QXa6pcaNt1HkwVsOPMBV6LD/q9oSpxNSYZQYkAnjdMjrJ86UuYeLo+aEZClV6opnw==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/transform": "^26.6.2", + "@jest/types": "^26.6.2", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.2", + "graceful-fs": "^4.2.4", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^4.0.3", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.2", + "jest-haste-map": "^26.6.2", + "jest-resolve": "^26.6.2", + "jest-util": "^26.6.2", + "jest-worker": "^26.6.2", + "slash": "^3.0.0", + "source-map": "^0.6.0", + "string-length": "^4.0.1", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^7.0.0" + }, + "engines": { + "node": ">= 10.14.2" + }, + "optionalDependencies": { + "node-notifier": "^8.0.0" + } + }, + "node_modules/@jest/reporters/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/@jest/reporters/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "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/@jest/reporters/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/@jest/source-map": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.6.2.tgz", + "integrity": "sha512-YwYcCwAnNmOVsZ8mr3GfnzdXDAl4LaenZP5z+G0c8bzC9/dugL8zRmxZzdoTl4IaS3CryS1uWnROLPFmb6lVvA==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.4", + "source-map": "^0.6.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/@jest/test-result": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.6.2.tgz", + "integrity": "sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ==", + "dev": true, + "dependencies": { + "@jest/console": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.6.3.tgz", + "integrity": "sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^26.6.2", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^26.6.2", + "jest-runner": "^26.6.3", + "jest-runtime": "^26.6.3" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "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/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/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jupyter-widgets/base": { + "version": "6.0.7", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@jupyterlab/services": "^6.0.0 || ^7.0.0", + "@lumino/coreutils": "^1.11.1 || ^2.1", + "@lumino/messaging": "^1.10.1 || ^2.1", + "@lumino/widgets": "^1.30.0 || ^2.1", + "@types/backbone": "1.4.14", + "@types/lodash": "^4.14.134", + "backbone": "1.4.0", + "jquery": "^3.1.1", + "lodash": "^4.17.4" + } + }, + "node_modules/@jupyter/ydoc": { + "version": "1.1.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@jupyterlab/nbformat": "^3.0.0 || ^4.0.0-alpha.21 || ^4.0.0", + "@lumino/coreutils": "^1.11.0 || ^2.0.0", + "@lumino/disposable": "^1.10.0 || ^2.0.0", + "@lumino/signaling": "^1.10.0 || ^2.0.0", + "y-protocols": "^1.0.5", + "yjs": "^13.5.40" + } + }, + "node_modules/@jupyterlab/coreutils": { + "version": "6.1.5", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@lumino/coreutils": "^2.1.2", + "@lumino/disposable": "^2.1.2", + "@lumino/signaling": "^2.1.2", + "minimist": "~1.2.0", + "path-browserify": "^1.0.0", + "url-parse": "~1.5.4" } }, "node_modules/@jupyterlab/nbformat": { "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@jupyterlab/nbformat/-/nbformat-4.1.5.tgz", - "integrity": "sha512-N9X3wxeh8BS5+pGIJGd7CyhVJI7l4XybAHnsN3sVJmL6RIlhji/zWzT0L/oAl3490sQdm+P/sLdiTWJqMHVYbg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@lumino/coreutils": "^2.1.2" } }, "node_modules/@jupyterlab/services": { "version": "7.1.5", - "resolved": "https://registry.npmjs.org/@jupyterlab/services/-/services-7.1.5.tgz", - "integrity": "sha512-OuG/dElnNgynDMGt9wXGuvL5AD6KjZeZzrFXqYT5YUurSkfTMX02PNh7x7xRWBNkwSmWJ63q/Iyrd4bJopLYpA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@jupyter/ydoc": "^1.1.1", "@jupyterlab/coreutils": "^6.1.5", @@ -969,9 +1688,8 @@ }, "node_modules/@jupyterlab/settingregistry": { "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@jupyterlab/settingregistry/-/settingregistry-4.1.5.tgz", - "integrity": "sha512-IjXEq9fsWxgZtShYOqhlH/FtPWB9D3qOMDfJm8mPBd7PUbRmxDPNAUdzdKLg01PCRb/WzOG4/Q5VBPHEH/1lzQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@jupyterlab/nbformat": "^4.1.5", "@jupyterlab/statedb": "^4.1.5", @@ -989,9 +1707,8 @@ }, "node_modules/@jupyterlab/statedb": { "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@jupyterlab/statedb/-/statedb-4.1.5.tgz", - "integrity": "sha512-/xA7HDuGhqO/H67kkXxc1/Ftqabg/pnurmiY895DEwU0NK8nutKk6g3RbRXA7AvIC/MoPdJCPr3mgNwJtldAuA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@lumino/commands": "^2.2.0", "@lumino/coreutils": "^2.1.2", @@ -1002,9 +1719,8 @@ }, "node_modules/@koa/cors": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@koa/cors/-/cors-5.0.0.tgz", - "integrity": "sha512-x/iUDjcS90W69PryLDIMgFyV21YLTnG9zOpPXS7Bkt2b8AsY3zZsIpOLBkYr9fBcF3HbkKaER5hOBZLfpLgYNw==", "dev": true, + "license": "MIT", "dependencies": { "vary": "^1.1.2" }, @@ -1014,9 +1730,8 @@ }, "node_modules/@koa/router": { "version": "13.1.0", - "resolved": "https://registry.npmjs.org/@koa/router/-/router-13.1.0.tgz", - "integrity": "sha512-mNVu1nvkpSd8Q8gMebGbCkDWJ51ODetrFvLKYusej+V0ByD4btqHYnPIzTBLXnQMVUlm/oxVwqmWBY3zQfZilw==", "dev": true, + "license": "MIT", "dependencies": { "http-errors": "^2.0.0", "koa-compose": "^4.1.0", @@ -1028,30 +1743,26 @@ }, "node_modules/@lumino/algorithm": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@lumino/algorithm/-/algorithm-2.0.1.tgz", - "integrity": "sha512-iA+uuvA7DeNFB0/cQpIWNgO1c6z4pOSigifjstLy+rxf1U5ZzxIq+xudnEuTbWgKSTviG02j4cKwCyx1PO6rzA==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@lumino/collections": { "version": "1.9.3", - "resolved": "https://registry.npmjs.org/@lumino/collections/-/collections-1.9.3.tgz", - "integrity": "sha512-2i2Wf1xnfTgEgdyKEpqM16bcYRIhUOGCDzaVCEZACVG9R1CgYwOe3zfn71slBQOVSjjRgwYrgLXu4MBpt6YK+g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@lumino/algorithm": "^1.9.2" } }, "node_modules/@lumino/collections/node_modules/@lumino/algorithm": { "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@lumino/algorithm/-/algorithm-1.9.2.tgz", - "integrity": "sha512-Z06lp/yuhz8CtIir3PNTGnuk7909eXt4ukJsCzChsGuot2l5Fbs96RJ/FOHgwCedaX74CtxPjXHXoszFbUA+4A==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@lumino/commands": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@lumino/commands/-/commands-2.3.0.tgz", - "integrity": "sha512-qOF9p9W54IWjyXrbd9QKr0d5XIn5ZTh6PBFO4UBGvEJJPO477tDm0f36HUxMMRtdJvp5ArgTj5/Khd3L3BFayg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@lumino/algorithm": "^2.0.1", "@lumino/coreutils": "^2.1.2", @@ -1064,30 +1775,26 @@ }, "node_modules/@lumino/coreutils": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@lumino/coreutils/-/coreutils-2.1.2.tgz", - "integrity": "sha512-vyz7WzchTO4HQ8iVAxvSUmb5o/8t3cz1vBo8V4ZIaPGada0Jx0xe3tKQ8bXp4pjHc+AEhMnkCnlUyVYMWbnj4A==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@lumino/disposable": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@lumino/disposable/-/disposable-2.1.2.tgz", - "integrity": "sha512-0qmB6zPt9+uj4SVMTfISn0wUOjYHahtKotwxDD5flfcscj2gsXaFCXO4Oqot1zcsZbg8uJmTUhEzAvFW0QhFNA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@lumino/signaling": "^2.1.2" } }, "node_modules/@lumino/domutils": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@lumino/domutils/-/domutils-2.0.1.tgz", - "integrity": "sha512-tbcfhsdKH04AMjSgYAYGD2xE80YcjrqKnfMTeU2NHt4J294Hzxs1GvEmSMk5qJ3Bbgwx6Z4BbQ7apnFg8Gc6cA==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@lumino/dragdrop": { "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@lumino/dragdrop/-/dragdrop-2.1.4.tgz", - "integrity": "sha512-/ckaYPHIZC1Ff0pU2H3WDI/Xm7V3i0XnyYG4PeZvG1+ovc0I0zeZtlb6qZXne0Vi2r8L2a0624FjF2CwwgNSnA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@lumino/coreutils": "^2.1.2", "@lumino/disposable": "^2.1.2" @@ -1095,15 +1802,13 @@ }, "node_modules/@lumino/keyboard": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@lumino/keyboard/-/keyboard-2.0.1.tgz", - "integrity": "sha512-R2mrH9HCEcv/0MSAl7bEUbjCNOnhrg49nXZBEVckg//TEG+sdayCsyrbJNMPcZ07asIPKc6mq3v7DpAmDKqh+w==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@lumino/messaging": { "version": "1.10.3", - "resolved": "https://registry.npmjs.org/@lumino/messaging/-/messaging-1.10.3.tgz", - "integrity": "sha512-F/KOwMCdqvdEG8CYAJcBSadzp6aI7a47Fr60zAKGqZATSRRRV41q53iXU7HjFPqQqQIvdn9Z7J32rBEAyQAzww==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@lumino/algorithm": "^1.9.2", "@lumino/collections": "^1.9.3" @@ -1111,15 +1816,13 @@ }, "node_modules/@lumino/messaging/node_modules/@lumino/algorithm": { "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@lumino/algorithm/-/algorithm-1.9.2.tgz", - "integrity": "sha512-Z06lp/yuhz8CtIir3PNTGnuk7909eXt4ukJsCzChsGuot2l5Fbs96RJ/FOHgwCedaX74CtxPjXHXoszFbUA+4A==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@lumino/polling": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@lumino/polling/-/polling-2.1.2.tgz", - "integrity": "sha512-hv6MT7xuSrw2gW4VIoiz3L366ZdZz4oefht+7HIW/VUB6seSDp0kVyZ4P9P4I4s/LauuzPqru3eWr7QAsFZyGA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@lumino/coreutils": "^2.1.2", "@lumino/disposable": "^2.1.2", @@ -1128,15 +1831,13 @@ }, "node_modules/@lumino/properties": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@lumino/properties/-/properties-2.0.1.tgz", - "integrity": "sha512-RPtHrp8cQqMnTC915lOIdrmsbPDCC7PhPOZb2YY7/Jj6dEdwmGhoMthc2tBEYWoHP+tU/hVm8UR/mEQby22srQ==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@lumino/signaling": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@lumino/signaling/-/signaling-2.1.2.tgz", - "integrity": "sha512-KtwKxx+xXkLOX/BdSqtvnsqBTPKDIENFBKeYkMTxstQc3fHRmyTzmaVoeZES+pr1EUy3e8vM4pQFVQpb8VsDdA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@lumino/algorithm": "^2.0.1", "@lumino/coreutils": "^2.1.2" @@ -1144,18 +1845,16 @@ }, "node_modules/@lumino/virtualdom": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@lumino/virtualdom/-/virtualdom-2.0.1.tgz", - "integrity": "sha512-WNM+uUZX7vORhlDRN9NmhEE04Tz1plDjtbwsX+i/51pQj2N2r7+gsVPY/gR4w+I5apmC3zG8/BojjJYIwi8ogA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@lumino/algorithm": "^2.0.1" } }, "node_modules/@lumino/widgets": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@lumino/widgets/-/widgets-2.3.2.tgz", - "integrity": "sha512-IUx4VNplRS9V+6RqG7K46QAnf5OzhcjZ3Us6WcZzcEO9K5FD73BK914rnFAat4BnWScdTAdZGUGKOvLPT9kuNA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@lumino/algorithm": "^2.0.1", "@lumino/commands": "^2.3.0", @@ -1172,50 +1871,99 @@ }, "node_modules/@lumino/widgets/node_modules/@lumino/collections": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@lumino/collections/-/collections-2.0.1.tgz", - "integrity": "sha512-8TbAU/48XVPKc/FOhGHLuugf2Gmx6vhVEx867KGG5fLwDOI8EW4gTno78yJUk8G0QpgNa+sdpB/LwbJFNIratg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@lumino/algorithm": "^2.0.1" } }, "node_modules/@lumino/widgets/node_modules/@lumino/messaging": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@lumino/messaging/-/messaging-2.0.1.tgz", - "integrity": "sha512-Z1b9Sq7i2yw7BN/u9ezoBUMYK06CsQXO7BqpczSnEO0PfwFf9dWi7y9VcIySOBz9uogsT1uczZMIMtLefk+xPQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@lumino/algorithm": "^2.0.1", "@lumino/collections": "^2.0.1" } }, - "node_modules/@microsoft/1ds-core-js": { - "version": "3.2.17", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-core-js/-/1ds-core-js-3.2.17.tgz", - "integrity": "sha512-S9EgWfY9NP0oiB3sdsTL41hJ71rbQzz9ziijQjHoklFADv+vKNe/TbOAgupBKAW04FaL0wmfE7HGF7mao84hUw==", + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", "dev": true, "dependencies": { - "@microsoft/applicationinsights-core-js": "2.8.18", - "@microsoft/applicationinsights-shims": "^2.0.2", - "@microsoft/dynamicproto-js": "^1.1.11" + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" } }, - "node_modules/@microsoft/1ds-post-js": { - "version": "3.2.17", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-post-js/-/1ds-post-js-3.2.17.tgz", - "integrity": "sha512-YD/pGW/WqijRFEZ/1sSdlkFVM2ZWLGQIMDxRD6/o58c3cC5jzG5PlR1PLp314jFjpUrBc4cmico+WAOP548z4w==", + "node_modules/@mapbox/node-pre-gyp/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": { - "@microsoft/1ds-core-js": "3.2.17", + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@mapbox/node-pre-gyp/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==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@microsoft/1ds-core-js": { + "version": "3.2.17", + "dev": true, + "license": "MIT", + "dependencies": { + "@microsoft/applicationinsights-core-js": "2.8.18", + "@microsoft/applicationinsights-shims": "^2.0.2", + "@microsoft/dynamicproto-js": "^1.1.11" + } + }, + "node_modules/@microsoft/1ds-post-js": { + "version": "3.2.17", + "dev": true, + "license": "MIT", + "dependencies": { + "@microsoft/1ds-core-js": "3.2.17", "@microsoft/applicationinsights-shims": "^2.0.2", "@microsoft/dynamicproto-js": "^1.1.11" } }, "node_modules/@microsoft/applicationinsights-channel-js": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-3.1.2.tgz", - "integrity": "sha512-QyPxpOOhtohFzcl4tzfWp4seN6JaToF66DZ1qjsYkUmEyHAackWSsv9m7qvuaAcCB9WrUzW9y0mRXgGKsEJcAg==", "dev": true, + "license": "MIT", "dependencies": { "@microsoft/applicationinsights-common": "3.1.2", "@microsoft/applicationinsights-core-js": "3.1.2", @@ -1230,9 +1978,8 @@ }, "node_modules/@microsoft/applicationinsights-channel-js/node_modules/@microsoft/applicationinsights-core-js": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-3.1.2.tgz", - "integrity": "sha512-xsJAm52tV355S/MogTunV/m1wg6P6tFg9Yhi4AC2OE9p2aa0k/FYHzWmrCrsEAVimCd8n/iTXmMRSrQk5QpxiA==", "dev": true, + "license": "MIT", "dependencies": { "@microsoft/applicationinsights-shims": "3.0.1", "@microsoft/dynamicproto-js": "^2.0.3", @@ -1245,27 +1992,24 @@ }, "node_modules/@microsoft/applicationinsights-channel-js/node_modules/@microsoft/applicationinsights-shims": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-shims/-/applicationinsights-shims-3.0.1.tgz", - "integrity": "sha512-DKwboF47H1nb33rSUfjqI6ryX29v+2QWcTrRvcQDA32AZr5Ilkr7whOOSsD1aBzwqX0RJEIP1Z81jfE3NBm/Lg==", "dev": true, + "license": "MIT", "dependencies": { "@nevware21/ts-utils": ">= 0.9.4 < 2.x" } }, "node_modules/@microsoft/applicationinsights-channel-js/node_modules/@microsoft/dynamicproto-js": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@microsoft/dynamicproto-js/-/dynamicproto-js-2.0.3.tgz", - "integrity": "sha512-JTWTU80rMy3mdxOjjpaiDQsTLZ6YSGGqsjURsY6AUQtIj0udlF/jYmhdLZu8693ZIC0T1IwYnFa0+QeiMnziBA==", "dev": true, + "license": "MIT", "dependencies": { "@nevware21/ts-utils": ">= 0.10.4 < 2.x" } }, "node_modules/@microsoft/applicationinsights-common": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-common/-/applicationinsights-common-3.1.2.tgz", - "integrity": "sha512-ivu3s73xt6Owakepnx2mbrMCry1mVHrA/2TL4nKCRLad6O3IBK3MkruMoeb3hoWpECBhErFRVj+/b0Kh7dl/Lw==", "dev": true, + "license": "MIT", "dependencies": { "@microsoft/applicationinsights-core-js": "3.1.2", "@microsoft/applicationinsights-shims": "3.0.1", @@ -1278,9 +2022,8 @@ }, "node_modules/@microsoft/applicationinsights-common/node_modules/@microsoft/applicationinsights-core-js": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-3.1.2.tgz", - "integrity": "sha512-xsJAm52tV355S/MogTunV/m1wg6P6tFg9Yhi4AC2OE9p2aa0k/FYHzWmrCrsEAVimCd8n/iTXmMRSrQk5QpxiA==", "dev": true, + "license": "MIT", "dependencies": { "@microsoft/applicationinsights-shims": "3.0.1", "@microsoft/dynamicproto-js": "^2.0.3", @@ -1293,27 +2036,24 @@ }, "node_modules/@microsoft/applicationinsights-common/node_modules/@microsoft/applicationinsights-shims": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-shims/-/applicationinsights-shims-3.0.1.tgz", - "integrity": "sha512-DKwboF47H1nb33rSUfjqI6ryX29v+2QWcTrRvcQDA32AZr5Ilkr7whOOSsD1aBzwqX0RJEIP1Z81jfE3NBm/Lg==", "dev": true, + "license": "MIT", "dependencies": { "@nevware21/ts-utils": ">= 0.9.4 < 2.x" } }, "node_modules/@microsoft/applicationinsights-common/node_modules/@microsoft/dynamicproto-js": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@microsoft/dynamicproto-js/-/dynamicproto-js-2.0.3.tgz", - "integrity": "sha512-JTWTU80rMy3mdxOjjpaiDQsTLZ6YSGGqsjURsY6AUQtIj0udlF/jYmhdLZu8693ZIC0T1IwYnFa0+QeiMnziBA==", "dev": true, + "license": "MIT", "dependencies": { "@nevware21/ts-utils": ">= 0.10.4 < 2.x" } }, "node_modules/@microsoft/applicationinsights-core-js": { "version": "2.8.18", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.18.tgz", - "integrity": "sha512-yPHRZFLpnEO0uSgFPM1BLMRRwjoten9YBbn4pJRbCT4PigLnj748knmWsMwXIdcehtkRTYz78kPYa/LWP7nvmA==", "dev": true, + "license": "MIT", "dependencies": { "@microsoft/applicationinsights-shims": "2.0.2", "@microsoft/dynamicproto-js": "^1.1.11" @@ -1324,15 +2064,13 @@ }, "node_modules/@microsoft/applicationinsights-shims": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.2.tgz", - "integrity": "sha512-PoHEgsnmcqruLNHZ/amACqdJ6YYQpED0KSRe6J7gIJTtpZC1FfFU9b1fmDKDKtFoUSrPzEh1qzO3kmRZP0betg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@microsoft/applicationinsights-web-basic": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-3.1.2.tgz", - "integrity": "sha512-NUnAk/ML9ClnmiQQRo3Fq2obzJVZAfGTgkQOwobZMvNhBVK5IPuv/ROEEAVbl02Go9AjV5uCZ+QoRhTfWrIumQ==", "dev": true, + "license": "MIT", "dependencies": { "@microsoft/applicationinsights-channel-js": "3.1.2", "@microsoft/applicationinsights-common": "3.1.2", @@ -1348,9 +2086,8 @@ }, "node_modules/@microsoft/applicationinsights-web-basic/node_modules/@microsoft/applicationinsights-core-js": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-3.1.2.tgz", - "integrity": "sha512-xsJAm52tV355S/MogTunV/m1wg6P6tFg9Yhi4AC2OE9p2aa0k/FYHzWmrCrsEAVimCd8n/iTXmMRSrQk5QpxiA==", "dev": true, + "license": "MIT", "dependencies": { "@microsoft/applicationinsights-shims": "3.0.1", "@microsoft/dynamicproto-js": "^2.0.3", @@ -1363,60 +2100,51 @@ }, "node_modules/@microsoft/applicationinsights-web-basic/node_modules/@microsoft/applicationinsights-shims": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-shims/-/applicationinsights-shims-3.0.1.tgz", - "integrity": "sha512-DKwboF47H1nb33rSUfjqI6ryX29v+2QWcTrRvcQDA32AZr5Ilkr7whOOSsD1aBzwqX0RJEIP1Z81jfE3NBm/Lg==", "dev": true, + "license": "MIT", "dependencies": { "@nevware21/ts-utils": ">= 0.9.4 < 2.x" } }, "node_modules/@microsoft/applicationinsights-web-basic/node_modules/@microsoft/dynamicproto-js": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@microsoft/dynamicproto-js/-/dynamicproto-js-2.0.3.tgz", - "integrity": "sha512-JTWTU80rMy3mdxOjjpaiDQsTLZ6YSGGqsjURsY6AUQtIj0udlF/jYmhdLZu8693ZIC0T1IwYnFa0+QeiMnziBA==", "dev": true, + "license": "MIT", "dependencies": { "@nevware21/ts-utils": ">= 0.10.4 < 2.x" } }, "node_modules/@microsoft/applicationinsights-web-snippet": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-web-snippet/-/applicationinsights-web-snippet-1.0.1.tgz", - "integrity": "sha512-2IHAOaLauc8qaAitvWS+U931T+ze+7MNWrDHY47IENP5y2UA0vqJDu67kWZDdpCN1fFC77sfgfB+HV7SrKshnQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@microsoft/dynamicproto-js": { "version": "1.1.11", - "resolved": "https://registry.npmjs.org/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.11.tgz", - "integrity": "sha512-gNw9z9LbqLV+WadZ6/MMrWwO3e0LuoUH1wve/1iPsBNbgqeVCiB0EZFNNj2lysxS2gkqoF9hmyVaG3MoM1BkxA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@microsoft/quantum-viz.js": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@microsoft/quantum-viz.js/-/quantum-viz.js-1.0.5.tgz", - "integrity": "sha512-U2atugL4j+p/yiioPR/TfqqR534iP6kEa10S+YNUW68UyvMe8eXNDFlb8GG4Ro9WSGobyLa8tP7iRiR2YMZO1w==", - "dev": true + "resolved": "circuit_vis", + "link": true }, "node_modules/@nevware21/ts-async": { "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@nevware21/ts-async/-/ts-async-0.5.0.tgz", - "integrity": "sha512-fJ2wSl5fd4UWoWbnXpPVKRg2Uw6u4+o9RsBHb35tiaOajVxJ97LrKAtrCGi6E19GpgfQbAWRFvz/iDXe3XCjWQ==", "dev": true, + "license": "MIT", "dependencies": { "@nevware21/ts-utils": ">= 0.11.0 < 2.x" } }, "node_modules/@nevware21/ts-utils": { "version": "0.11.1", - "resolved": "https://registry.npmjs.org/@nevware21/ts-utils/-/ts-utils-0.11.1.tgz", - "integrity": "sha512-1QZSZ39UzjC8MR0+LRO2l8ITFHYdCZeHfBG9p3XUCz0hQ22I0Pf/XE5EF+TPSJK3LLME3pUNx2MCQ4XEtOHv+g==", - "dev": true + "dev": true, + "license": "MIT" }, "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, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -1427,18 +2155,16 @@ }, "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, + "license": "MIT", "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, + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -1447,20 +2173,42 @@ "node": ">= 8" } }, + "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==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "dev": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@opentelemetry/api": { "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.8.0.tgz", - "integrity": "sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=8.0.0" } }, "node_modules/@opentelemetry/core": { "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.22.0.tgz", - "integrity": "sha512-0VoAlT6x+Xzik1v9goJ3pZ2ppi6+xd3aUfg4brfrLkDBHRIVjMP0eBHrKrhB+NKcDyMAg8fAbGL3Npg/F6AwWA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@opentelemetry/semantic-conventions": "1.22.0" }, @@ -1473,9 +2221,8 @@ }, "node_modules/@opentelemetry/instrumentation": { "version": "0.41.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.41.2.tgz", - "integrity": "sha512-rxU72E0pKNH6ae2w5+xgVYZLzc5mlxAbGzF4shxMVK8YC2QQsfN38B2GPbj0jvrKWWNUElfclQ+YTykkNg/grw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@types/shimmer": "^1.0.2", "import-in-the-middle": "1.4.2", @@ -1492,9 +2239,8 @@ }, "node_modules/@opentelemetry/resources": { "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.22.0.tgz", - "integrity": "sha512-+vNeIFPH2hfcNL0AJk/ykJXoUCtR1YaDUZM+p3wZNU4Hq98gzq+7b43xbkXjadD9VhWIUQqEwXyY64q6msPj6A==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "1.22.0", "@opentelemetry/semantic-conventions": "1.22.0" @@ -1508,9 +2254,8 @@ }, "node_modules/@opentelemetry/sdk-trace-base": { "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.22.0.tgz", - "integrity": "sha512-pfTuSIpCKONC6vkTpv6VmACxD+P1woZf4q0K46nSUvXFvOFqjBYKFaAMkKD3M1mlKUUh0Oajwj35qNjMl80m1Q==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "1.22.0", "@opentelemetry/resources": "1.22.0", @@ -1525,18 +2270,16 @@ }, "node_modules/@opentelemetry/semantic-conventions": { "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.22.0.tgz", - "integrity": "sha512-CAOgFOKLybd02uj/GhCdEeeBjOS0yeoDeo/CA7ASBSmenpZHAKGB3iDm/rv3BQLcabb/OprDEsSQ1y0P8A7Siw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=14" } }, "node_modules/@parcel/watcher": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.4.1.tgz", - "integrity": "sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==", "dev": true, + "license": "MIT", "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", @@ -1565,154 +2308,13 @@ "@parcel/watcher-win32-x64": "2.4.1" } }, - "node_modules/@parcel/watcher-android-arm64": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.4.1.tgz", - "integrity": "sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-darwin-arm64": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.4.1.tgz", - "integrity": "sha512-ln41eihm5YXIY043vBrrHfn94SIBlqOWmoROhsMVTSXGh0QahKGy77tfEywQ7v3NywyxBBkGIfrWRHm0hsKtzA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-darwin-x64": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.4.1.tgz", - "integrity": "sha512-yrw81BRLjjtHyDu7J61oPuSoeYWR3lDElcPGJyOvIXmor6DEo7/G2u1o7I38cwlcoBHQFULqF6nesIX3tsEXMg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-freebsd-x64": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.4.1.tgz", - "integrity": "sha512-TJa3Pex/gX3CWIx/Co8k+ykNdDCLx+TuZj3f3h7eOjgpdKM+Mnix37RYsYU4LHhiYJz3DK5nFCCra81p6g050w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm-glibc": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.4.1.tgz", - "integrity": "sha512-4rVYDlsMEYfa537BRXxJ5UF4ddNwnr2/1O4MHM5PjI9cvV2qymvhwZSFgXqbS8YoTk5i/JR0L0JDs69BUn45YA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm64-glibc": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.4.1.tgz", - "integrity": "sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm64-musl": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.4.1.tgz", - "integrity": "sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, "node_modules/@parcel/watcher-linux-x64-glibc": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.4.1.tgz", - "integrity": "sha512-s9O3fByZ/2pyYDPoLM6zt92yu6P4E39a03zvO0qCHOTjxmt3GHRMLuRZEWhWLASTMSrrnVNWdVI/+pUElJBBBg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -1727,12 +2329,11 @@ }, "node_modules/@parcel/watcher-linux-x64-musl": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.4.1.tgz", - "integrity": "sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -1745,72 +2346,11 @@ "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/watcher-win32-arm64": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.4.1.tgz", - "integrity": "sha512-Uq2BPp5GWhrq/lcuItCHoqxjULU1QYEcyjSO5jqqOK8RNFDBQnenMMx4gAl3v8GiWa59E9+uDM7yZ6LxwUIfRg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-ia32": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.4.1.tgz", - "integrity": "sha512-maNRit5QQV2kgHFSYwftmPBxiuK5u4DXjbXx7q6eKjq5dsLXZ4FJiVvlcw35QXzk0KrUecJmuVFbj4uV9oYrcw==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-x64": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.4.1.tgz", - "integrity": "sha512-+DvS92F9ezicfswqrvIRM2njcYJbd5mb9CUgtrHCHmvn7pPPa+nMDRu1o1bYYz/l5IB2NVGNJWiH7h1E58IF2A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, "node_modules/@playwright/browser-chromium": { "version": "1.47.2", - "resolved": "https://registry.npmjs.org/@playwright/browser-chromium/-/browser-chromium-1.47.2.tgz", - "integrity": "sha512-tsk9bLcGzIu4k4xI2ixlwDrdJhMqCalUCsSj7TRI8VuvK7cLiJIa5SR0dprKbX+wkku/JMR4EN6g9DMHvfna+Q==", "dev": true, "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { "playwright-core": "1.47.2" }, @@ -1820,9 +2360,8 @@ }, "node_modules/@rjsf/utils": { "version": "5.18.1", - "resolved": "https://registry.npmjs.org/@rjsf/utils/-/utils-5.18.1.tgz", - "integrity": "sha512-BxXd5C8gxOSDCSgfDT+XZHpBZtu4F0jJZsnMQstWJ+9QKpmTiuvbkjk3c1J4zZ3CRNgGghVH5otU5gvzVWIxpQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "json-schema-merge-allof": "^0.8.1", "jsonpointer": "^5.0.1", @@ -1837,57 +2376,164 @@ "react": "^16.14.0 || >=17" } }, - "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==", + "node_modules/@sinonjs/commons": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", "dev": true, - "engines": { - "node": ">= 10" + "dependencies": { + "type-detect": "4.0.8" } }, - "node_modules/@types/backbone": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@types/backbone/-/backbone-1.4.14.tgz", - "integrity": "sha512-85ldQ99fiYTJFBlZuAJRaCdvTZKZ2p1fSs3fVf+6Ub6k1X0g0hNJ0qJ/2FOByyyAQYLtbEz3shX5taKQfBKBDw==", + "node_modules/@sinonjs/fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", + "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", "dev": true, "dependencies": { - "@types/jquery": "*", - "@types/underscore": "*" + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/backbone": { + "version": "1.4.14", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/jquery": "*", + "@types/underscore": "*" } }, "node_modules/@types/chai": { "version": "4.3.14", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.14.tgz", - "integrity": "sha512-Wj71sXE4Q4AkGdG9Tvq1u/fquNz9EdG4LIJMwVVII7ashjD/8cf8fyIfJAjRr6YcsXnSE8cOGQPq1gqeR8z+3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", "dev": true }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "26.0.24", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.24.tgz", + "integrity": "sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w==", + "dev": true, + "dependencies": { + "jest-diff": "^26.0.0", + "pretty-format": "^26.0.0" + } + }, "node_modules/@types/jquery": { "version": "3.5.29", - "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.29.tgz", - "integrity": "sha512-oXQQC9X9MOPRrMhPHHOsXqeQDnWeCDT3PelUIg/Oy8FAbzSZtFHRjc7IpbfFVmpLtJ+UOoywpRsuO5Jxjybyeg==", "dev": true, + "license": "MIT", "dependencies": { "@types/sizzle": "*" } }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, "node_modules/@types/linkify-it": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/lodash": { "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.0.tgz", - "integrity": "sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/markdown-it": { "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.1.tgz", - "integrity": "sha512-4NpsnpYl2Gt1ljyBGrKMxFYAYvpqbnnkgP/i/g+NLpjEUa3obn1XJCur9YbEXKDAkaXqsR1LbDnGEJ0MmKFxfg==", "dev": true, + "license": "MIT", "dependencies": { "@types/linkify-it": "^5", "@types/mdurl": "^2" @@ -1895,60 +2541,84 @@ }, "node_modules/@types/mdurl": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/mocha": { "version": "10.0.6", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", - "integrity": "sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/node": { "version": "18.19.28", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.28.tgz", - "integrity": "sha512-J5cOGD9n4x3YGgVuaND6khm5x07MMdAKkRyXnjVR6KFhLMNh2yONGiP7Z+4+tBOt5mK+GvDTiacTOVGGpqiecw==", "dev": true, + "license": "MIT", "dependencies": { "undici-types": "~5.26.4" } }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true + }, + "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 + }, "node_modules/@types/shimmer": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.0.5.tgz", - "integrity": "sha512-9Hp0ObzwwO57DpLFF0InUjUm/II8GmKAvzbefxQTihCb7KI6yc9yzf0nLc4mVdby5N4DRCgQM2wCup9KTieeww==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/sizzle": { "version": "2.3.8", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.8.tgz", - "integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", "dev": true }, "node_modules/@types/underscore": { "version": "1.11.15", - "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.11.15.tgz", - "integrity": "sha512-HP38xE+GuWGlbSRq9WrZkousaQ7dragtZCruBVMi0oX1migFZavZ3OROKHSkNp/9ouq82zrWtZpg18jFnVN96g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/vscode": { "version": "1.87.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.87.0.tgz", - "integrity": "sha512-y3yYJV2esWr8LNjp3VNbSMWG7Y43jC8pCldG8YwiHGAQbsymkkMMt0aDT1xZIOFM2eFcNiUc+dJMx1+Z0UT8fg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/vscode-webview": { "version": "1.57.5", - "resolved": "https://registry.npmjs.org/@types/vscode-webview/-/vscode-webview-1.57.5.tgz", - "integrity": "sha512-iBAUYNYkz+uk1kdsq05fEcoh8gJmwT3lqqFPN7MGyjQ3HVloViMdo7ZJ8DFIP8WOK74PjOEilosqAyxV2iUFUw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "15.0.19", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz", + "integrity": "sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.3.0.tgz", - "integrity": "sha512-FLAIn63G5KH+adZosDYiutqkOkYEx0nvcwNNfJAf+c7Ae/H35qWwTYvPZUKFj5AS+WfHG/WJJfWnDnyNUlp8UA==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.3.0", @@ -1979,9 +2649,8 @@ }, "node_modules/@typescript-eslint/parser": { "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.3.0.tgz", - "integrity": "sha512-h53RhVyLu6AtpUzVCYLPhZGL5jzTD9fZL+SYf/+hYOx2bDkyQXztXSc4tbvKYHzfMXExMLiL9CWqJmVz6+78IQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/scope-manager": "8.3.0", "@typescript-eslint/types": "8.3.0", @@ -2007,9 +2676,8 @@ }, "node_modules/@typescript-eslint/scope-manager": { "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.3.0.tgz", - "integrity": "sha512-mz2X8WcN2nVu5Hodku+IR8GgCOl4C0G/Z1ruaWN4dgec64kDBabuXyPAr+/RgJtumv8EEkqIzf3X2U5DUKB2eg==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/types": "8.3.0", "@typescript-eslint/visitor-keys": "8.3.0" @@ -2024,9 +2692,8 @@ }, "node_modules/@typescript-eslint/type-utils": { "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.3.0.tgz", - "integrity": "sha512-wrV6qh//nLbfXZQoj32EXKmwHf4b7L+xXLrP3FZ0GOUU72gSvLjeWUl5J5Ue5IwRxIV1TfF73j/eaBapxx99Lg==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/typescript-estree": "8.3.0", "@typescript-eslint/utils": "8.3.0", @@ -2048,9 +2715,8 @@ }, "node_modules/@typescript-eslint/types": { "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.3.0.tgz", - "integrity": "sha512-y6sSEeK+facMaAyixM36dQ5NVXTnKWunfD1Ft4xraYqxP0lC0POJmIaL/mw72CUMqjY9qfyVfXafMeaUj0noWw==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -2061,9 +2727,8 @@ }, "node_modules/@typescript-eslint/typescript-estree": { "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.3.0.tgz", - "integrity": "sha512-Mq7FTHl0R36EmWlCJWojIC1qn/ZWo2YiWYc1XVtasJ7FIgjo0MVv9rZWXEE7IK2CGrtwe1dVOxWwqXUdNgfRCA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/types": "8.3.0", "@typescript-eslint/visitor-keys": "8.3.0", @@ -2089,9 +2754,8 @@ }, "node_modules/@typescript-eslint/utils": { "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.3.0.tgz", - "integrity": "sha512-F77WwqxIi/qGkIGOGXNBLV7nykwfjLsdauRB/DOFPdv6LTF3BHHkBpq81/b5iMPSF055oO2BiivDJV4ChvNtXA==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "8.3.0", @@ -2111,9 +2775,8 @@ }, "node_modules/@typescript-eslint/visitor-keys": { "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.3.0.tgz", - "integrity": "sha512-RmZwrTbQ9QveF15m/Cl28n0LXD6ea2CjkhH5rQ55ewz3H24w+AMCJHPVYaZ8/0HoG8Z3cLLFFycRXxeO2tz9FA==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/types": "8.3.0", "eslint-visitor-keys": "^3.4.3" @@ -2128,9 +2791,8 @@ }, "node_modules/@vscode/debugadapter": { "version": "1.65.0", - "resolved": "https://registry.npmjs.org/@vscode/debugadapter/-/debugadapter-1.65.0.tgz", - "integrity": "sha512-l9jdX0GFoFVAc7O4O8iVnCjO0pgxbx+wJJXCaYSuglGtYwMNcJdc7xm96cuVx4LWzSqneIjvjzbuzZtoVZhZzQ==", "dev": true, + "license": "MIT", "dependencies": { "@vscode/debugprotocol": "1.65.0" }, @@ -2140,15 +2802,13 @@ }, "node_modules/@vscode/debugprotocol": { "version": "1.65.0", - "resolved": "https://registry.npmjs.org/@vscode/debugprotocol/-/debugprotocol-1.65.0.tgz", - "integrity": "sha512-ejerrPMBXzYms6Ks+Gb7cdXtdncmT0xwIKNsc0c/SxhEa0HVY5jdvLUegYE91p7CQJpCnXOD/r2CvViN8txLLA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@vscode/extension-telemetry": { "version": "0.8.5", - "resolved": "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-0.8.5.tgz", - "integrity": "sha512-YFKANBT2F3qdWQstjcr40XX8BLsdKlKM7a7YPi/jNuMjuiPhb1Jn7YsDR3WZaVEzAqeqGy4gzXsFCBbuZ+L1Tg==", "dev": true, + "license": "MIT", "dependencies": { "@microsoft/1ds-core-js": "^3.2.13", "@microsoft/1ds-post-js": "^3.2.13", @@ -2161,18 +2821,16 @@ }, "node_modules/@vscode/markdown-it-katex": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@vscode/markdown-it-katex/-/markdown-it-katex-1.0.3.tgz", - "integrity": "sha512-a8ppdac0CG2lAQC6E6lT8dxmXkUk9gRtYNtILx31FyrPEwj875AAHc6tpRGeJBpWMpiMtcvz7ymWYBwYgxuFmw==", "dev": true, + "license": "MIT", "dependencies": { "katex": "^0.16.4" } }, "node_modules/@vscode/test-web": { "version": "0.0.61", - "resolved": "https://registry.npmjs.org/@vscode/test-web/-/test-web-0.0.61.tgz", - "integrity": "sha512-633yh0WuhUkmY+LEjzDdhEhMgUN+nXJRJbVy8iDiT/IzPsDx7ihEIOnnPPnHKpVyErOIYquNTG8n51dYtaxdbQ==", "dev": true, + "license": "MIT", "dependencies": { "@koa/cors": "^5.0.0", "@koa/router": "^13.1.0", @@ -2199,9 +2857,8 @@ }, "node_modules/@vscode/test-web/node_modules/glob": { "version": "11.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", - "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", "dev": true, + "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^4.0.1", @@ -2222,9 +2879,8 @@ }, "node_modules/@vscode/test-web/node_modules/minimatch": { "version": "10.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", - "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -2235,11 +2891,225 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@webassemblyjs/ast": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", + "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", + "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", + "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.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/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "deprecated": "Use your platform's native atob() and btoa() methods instead", + "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, + "license": "MIT", "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -2250,8 +3120,29 @@ }, "node_modules/acorn": { "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "license": "MIT", + "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-globals/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" @@ -2262,8 +3153,16 @@ }, "node_modules/acorn-import-assertions": { "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", "dev": true, "peerDependencies": { "acorn": "^8" @@ -2271,18 +3170,25 @@ }, "node_modules/acorn-jsx": { "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/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/agent-base": { "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.3.4" }, @@ -2290,11 +3196,23 @@ "node": ">= 14" } }, + "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": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -2308,27 +3226,39 @@ }, "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, + "license": "MIT", "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-regex": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "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==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -2341,9 +3271,8 @@ }, "node_modules/anymatch": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -2354,9 +3283,8 @@ }, "node_modules/applicationinsights": { "version": "2.9.5", - "resolved": "https://registry.npmjs.org/applicationinsights/-/applicationinsights-2.9.5.tgz", - "integrity": "sha512-APQ8IWyYDHFvKbitFKpsmZXxkzQh0yYTFacQqoVW7HwlPo3eeLprwnq5RFNmmG6iqLmvQ+xRJSDLEQCgqPh+bw==", "dev": true, + "license": "MIT", "dependencies": { "@azure/core-auth": "^1.5.0", "@azure/core-rest-pipeline": "1.10.1", @@ -2384,26 +3312,102 @@ } } }, - "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==", + "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/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "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==", + "deprecated": "This package is no longer supported.", "dev": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "dev": true, + "license": "Python-2.0" + }, + "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-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": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", + "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/assertion-error": { + "version": "1.1.0", + "dev": true, + "license": "MIT", "engines": { "node": "*" } }, + "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/async-hook-jl": { "version": "1.7.6", - "resolved": "https://registry.npmjs.org/async-hook-jl/-/async-hook-jl-1.7.6.tgz", - "integrity": "sha512-gFaHkFfSxTjvoxDMYqDuGHlcRyUuamF8s+ZTtJdDzqjws4mCt7v0vuV79/E2Wr2/riMQgtG4/yUtXWs1gZ7JMg==", "dev": true, + "license": "MIT", "dependencies": { "stack-chain": "^1.3.7" }, @@ -2413,9 +3417,8 @@ }, "node_modules/async-listener": { "version": "0.6.10", - "resolved": "https://registry.npmjs.org/async-listener/-/async-listener-0.6.10.tgz", - "integrity": "sha512-gpuo6xOyF4D5DE5WvyqZdPA3NGhiT6Qf07l7DCB0wwDEsLvDIbCr6j9S5aj5Ch96dLace5tXVzWBZkxU/c5ohw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "semver": "^5.3.0", "shimmer": "^1.1.0" @@ -2426,52 +3429,177 @@ }, "node_modules/async-listener/node_modules/semver": { "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver" } }, "node_modules/asynckit": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "dev": true, + "license": "MIT" + }, + "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/b4a": { "version": "1.6.6", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", - "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==", - "dev": true + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/babel-jest": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.6.3.tgz", + "integrity": "sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA==", + "dev": true, + "dependencies": { + "@jest/transform": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/babel__core": "^7.1.7", + "babel-plugin-istanbul": "^6.0.0", + "babel-preset-jest": "^26.6.2", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "slash": "^3.0.0" + }, + "engines": { + "node": ">= 10.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.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, + "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.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "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.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.6.2.tgz", + "integrity": "sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw==", + "dev": 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.14.2" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@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" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.6.2.tgz", + "integrity": "sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^26.6.2", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": ">= 10.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } }, "node_modules/backbone": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/backbone/-/backbone-1.4.0.tgz", - "integrity": "sha512-RLmDrRXkVdouTg38jcgHhyQ/2zjg7a8E6sz2zxfz21Hh17xDJYUHBZimVIt5fUyS8vbfpeSmTL3gUjTEvUV3qQ==", "dev": true, + "license": "MIT", "dependencies": { "underscore": ">=1.8.3" } }, "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 + "dev": true, + "license": "MIT" }, "node_modules/bare-events": { "version": "2.4.2", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.4.2.tgz", - "integrity": "sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==", "dev": true, + "license": "Apache-2.0", "optional": true }, "node_modules/bare-fs": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.3.1.tgz", - "integrity": "sha512-W/Hfxc/6VehXlsgFtbB5B4xFcsCl+pAh30cYhoFyXErf6oGrwjh8SwiPAdHgpmWonKuYpZgGywN0SXt7dgsADA==", "dev": true, + "license": "Apache-2.0", "optional": true, "dependencies": { "bare-events": "^2.0.0", @@ -2481,16 +3609,14 @@ }, "node_modules/bare-os": { "version": "2.4.0", - "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.4.0.tgz", - "integrity": "sha512-v8DTT08AS/G0F9xrhyLtepoo9EJBJ85FRSMbu1pQUlAf6A8T0tEEQGMVObWeqpjhSPXsE0VGlluFBJu2fdoTNg==", "dev": true, + "license": "Apache-2.0", "optional": true }, "node_modules/bare-path": { "version": "2.1.3", - "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.3.tgz", - "integrity": "sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==", "dev": true, + "license": "Apache-2.0", "optional": true, "dependencies": { "bare-os": "^2.1.0" @@ -2498,19 +3624,47 @@ }, "node_modules/bare-stream": { "version": "2.1.3", - "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.1.3.tgz", - "integrity": "sha512-tiDAH9H/kP+tvNO5sczyn9ZAA7utrSMobyDchsnyyXBuUe2FSQWbxhtuHB8jwpHYYevVo2UJpcmvvjrbHboUUQ==", "dev": true, + "license": "Apache-2.0", "optional": true, "dependencies": { "streamx": "^2.18.0" } }, + "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/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, + "license": "MIT", "dependencies": { "safe-buffer": "5.1.2" }, @@ -2520,15 +3674,22 @@ }, "node_modules/basic-auth/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 + "dev": true, + "license": "MIT" + }, + "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.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -2538,18 +3699,16 @@ }, "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, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/braces": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, @@ -2557,32 +3716,191 @@ "node": ">=8" } }, + "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-stdout": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/browserify-zlib": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", - "integrity": "sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==", "dev": true, + "license": "MIT", "dependencies": { "pako": "~0.2.0" } }, + "node_modules/browserslist": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", + "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001663", + "electron-to-chromium": "^1.5.28", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.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, + "dependencies": { + "node-int64": "^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 + "dev": true, + "license": "MIT" + }, + "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/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/cacache/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "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/cacache/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/cacache/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", "dev": true, + "license": "MIT", "dependencies": { "mime-types": "^2.1.18", "ylru": "^1.2.0" @@ -2593,9 +3911,8 @@ }, "node_modules/call-bind": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -2612,18 +3929,16 @@ }, "node_modules/callsites": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/camelcase": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -2631,29 +3946,74 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/chai": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", - "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", + "node_modules/caniuse-lite": { + "version": "1.0.30001669", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001669.tgz", + "integrity": "sha512-DlWzFDJqstqtIVx1zeSpIMLjunf5SmwOw0N2Ck/QSQdS8PLS4+9HrLaYei4w8BIAL7IB/UEDu889d8vhCTPA0w==", "dev": true, - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.3", - "deep-eql": "^4.1.3", - "get-func-name": "^2.0.2", - "loupe": "^2.3.6", - "pathval": "^1.1.1", - "type-detect": "^4.0.8" - }, - "engines": { - "node": ">=4" + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/canvas": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz", + "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.0", + "nan": "^2.17.0", + "simple-get": "^3.0.3" + }, + "engines": { + "node": ">=6" + } + }, + "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/chai": { + "version": "4.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=4" } }, "node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -2665,11 +4025,19 @@ "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, + "engines": { + "node": ">=10" + } + }, "node_modules/check-error": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", "dev": true, + "license": "MIT", "dependencies": { "get-func-name": "^2.0.2" }, @@ -2679,8 +4047,6 @@ }, "node_modules/chokidar": { "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, "funding": [ { @@ -2688,6 +4054,7 @@ "url": "https://paulmillr.com/funding/" } ], + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -2706,9 +4073,8 @@ }, "node_modules/chokidar/node_modules/glob-parent": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -2716,28 +4082,112 @@ "node": ">= 6" } }, + "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.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "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/cjs-module-lexer": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", - "dev": true + "dev": true, + "license": "MIT" + }, + "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-descriptor": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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/cliui": { "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, + "node_modules/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/cls-hooked": { "version": "4.2.2", - "resolved": "https://registry.npmjs.org/cls-hooked/-/cls-hooked-4.2.2.tgz", - "integrity": "sha512-J4Xj5f5wq/4jAvcdgoGsL3G103BtWpZrMo8NEinRltN+xpTZdI+M38pyQqhuFU/P792xkMFvnKSf+Lm81U1bxw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "async-hook-jl": "^1.7.6", "emitter-listener": "^1.0.1", @@ -2749,28 +4199,44 @@ }, "node_modules/cls-hooked/node_modules/semver": { "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver" } }, "node_modules/co": { "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", "dev": true, + "license": "MIT", "engines": { "iojs": ">= 1.0.0", "node": ">= 0.12.0" } }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "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==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -2780,15 +4246,28 @@ }, "node_modules/color-name": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/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.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "dev": true }, "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, + "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, @@ -2798,17 +4277,29 @@ }, "node_modules/commander": { "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", "dev": true, + "license": "MIT", "engines": { "node": ">= 12" } }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, + "node_modules/component-emitter": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/compute-gcd": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/compute-gcd/-/compute-gcd-1.2.1.tgz", - "integrity": "sha512-TwMbxBNz0l71+8Sc4czv13h4kEqnchV9igQZBi6QUaz09dnz13juGnnaWWJTRsP3brxOoxeB4SA2WELLw1hCtg==", "dev": true, "dependencies": { "validate.io-array": "^1.0.3", @@ -2818,8 +4309,6 @@ }, "node_modules/compute-lcm": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/compute-lcm/-/compute-lcm-1.1.2.tgz", - "integrity": "sha512-OFNPdQAXnQhDSKioX8/XYT6sdUlXwpeMjfd6ApxMJfyZ4GxmLR1xvMERctlYhlHwIiz6CSpBc2+qYKjHGZw4TQ==", "dev": true, "dependencies": { "compute-gcd": "^1.2.1", @@ -2830,15 +4319,19 @@ }, "node_modules/concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/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==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" }, @@ -2848,28 +4341,31 @@ }, "node_modules/content-type": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/continuation-local-storage": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/continuation-local-storage/-/continuation-local-storage-3.2.1.tgz", - "integrity": "sha512-jx44cconVqkCEEyLSKWwkvUXwO561jXMa3LPjTPsm5QR22PA0/mhe33FT4Xb5y74JDvt/Cq+5lm8S8rskLv9ZA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "async-listener": "^0.6.0", "emitter-listener": "^1.1.1" } }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, "node_modules/cookies": { "version": "0.9.1", - "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.9.1.tgz", - "integrity": "sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==", "dev": true, + "license": "MIT", "dependencies": { "depd": "~2.0.0", "keygrip": "~1.1.0" @@ -2878,17 +4374,24 @@ "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/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 + "dev": true, + "license": "MIT" }, "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, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -2898,11 +4401,48 @@ "node": ">= 8" } }, + "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/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/debug": { "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -2917,9 +4457,8 @@ }, "node_modules/decamelize": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -2927,11 +4466,37 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "dev": true + }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "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/deep-eql": { "version": "4.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", - "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", "dev": true, + "license": "MIT", "dependencies": { "type-detect": "^4.0.0" }, @@ -2941,21 +4506,27 @@ }, "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==", - "dev": true + "dev": true, + "license": "MIT" }, "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 + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, "node_modules/define-data-property": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -2968,35 +4539,44 @@ "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/delayed-stream": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true, + "license": "MIT", "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==", - "dev": true + "dev": true, + "license": "MIT" }, "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, + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/destroy": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" @@ -3004,9 +4584,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, + "license": "Apache-2.0", "bin": { "detect-libc": "bin/detect-libc.js" }, @@ -3014,38 +4593,74 @@ "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, + "engines": { + "node": ">=8" + } + }, "node_modules/diagnostic-channel": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/diagnostic-channel/-/diagnostic-channel-1.1.1.tgz", - "integrity": "sha512-r2HV5qFkUICyoaKlBEpLKHjxMXATUf/l+h8UZPGBHGLy4DDiY2sOLcIctax4eRnTw5wH2jTMExLntGPJ8eOJxw==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^7.5.3" } }, "node_modules/diagnostic-channel-publishers": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.8.tgz", - "integrity": "sha512-HmSm9hXxSPxA9BaLGY98QU1zsdjeCk113KjAYGPCen1ZP6mhVaTPzHd6UYv5r21DnWANi+f+NyPOHruGT9jpqQ==", "dev": true, + "license": "MIT", "peerDependencies": { "diagnostic-channel": "*" } }, "node_modules/diff": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, + "node_modules/diff-sequences": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz", + "integrity": "sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==", + "dev": true, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "deprecated": "Use your platform's native DOMException instead", + "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/duplexify": { "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", "dev": true, + "license": "MIT", "dependencies": { "end-of-stream": "^1.0.0", "inherits": "^2.0.1", @@ -3055,54 +4670,88 @@ }, "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 + "dev": true, + "license": "MIT" }, "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.41", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.41.tgz", + "integrity": "sha512-dfdv/2xNjX0P8Vzme4cfzHqnPm5xsZXwsolTYr0eyW18IUmNyG08vL+fttvinTfhKfIKdRoqkDIC9e9iWQCNYQ==", "dev": true }, "node_modules/emitter-listener": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/emitter-listener/-/emitter-listener-1.1.2.tgz", - "integrity": "sha512-Bt1sBAGFHY9DKY+4/2cV6izcKJUf5T7/gkdmkxzX/qv9CcGH8xSwVRW5mtX03SWJtRTWSOpzCuWN9rBFYZepZQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "shimmer": "^1.2.0" } }, - "node_modules/emoji-regex": { + "node_modules/emittery": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.7.2.tgz", + "integrity": "sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ==", + "dev": 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 + "dev": true, + "license": "MIT" + }, + "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/encodeurl": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } }, "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, + "license": "MIT", "dependencies": { "once": "^1.4.0" } }, + "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/entities": { "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.12" }, @@ -3110,11 +4759,43 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/envinfo": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz", + "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "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-define-property": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", "dev": true, + "license": "MIT", "dependencies": { "get-intrinsic": "^1.2.4" }, @@ -3124,19 +4805,23 @@ }, "node_modules/es-errors": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" } }, + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "dev": true + }, "node_modules/esbuild": { "version": "0.23.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", - "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", "dev": true, "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, @@ -3171,9 +4856,9 @@ } }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "engines": { "node": ">=6" @@ -3181,15 +4866,13 @@ }, "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==", - "dev": true + "dev": true, + "license": "MIT" }, "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, + "license": "MIT", "engines": { "node": ">=10" }, @@ -3197,11 +4880,31 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, "node_modules/eslint": { "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.1.0.tgz", - "integrity": "sha512-1TCBecGFQtItia2o39P7Z4BK1X7ByNPxAiWJvwiyTGcOwYnTiiASgMpNA6a+beu8cFPhEDWvPf6mIlYUJv6sgA==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -3250,9 +4953,8 @@ }, "node_modules/eslint-scope": { "version": "8.0.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", - "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -3266,9 +4968,8 @@ }, "node_modules/eslint-visitor-keys": { "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -3278,18 +4979,16 @@ }, "node_modules/eslint/node_modules/@eslint/js": { "version": "9.1.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.1.1.tgz", - "integrity": "sha512-5WoDz3Y19Bg2BnErkZTp0en+c/i9PvgFS7MBe1+m60HjFr0hrphlAGp4yzI7pxpt4xShln4ZyYp4neJm8hmOkQ==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/eslint/node_modules/ajv": { "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -3303,9 +5002,8 @@ }, "node_modules/eslint/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, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3313,9 +5011,8 @@ }, "node_modules/eslint/node_modules/eslint-visitor-keys": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -3325,15 +5022,13 @@ }, "node_modules/eslint/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 + "dev": true, + "license": "MIT" }, "node_modules/eslint/node_modules/minimatch": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -3343,9 +5038,8 @@ }, "node_modules/espree": { "version": "10.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", - "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.12.0", "acorn-jsx": "^5.3.2", @@ -3360,9 +5054,8 @@ }, "node_modules/espree/node_modules/eslint-visitor-keys": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -3370,11 +5063,23 @@ "url": "https://opencollective.com/eslint" } }, + "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/esquery": { "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -3384,9 +5089,8 @@ }, "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, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -3396,48 +5100,247 @@ }, "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, + "license": "BSD-2-Clause", "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==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } }, "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, + "license": "MIT", "engines": { "node": ">=0.8.x" } }, + "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": "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/execa/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/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": 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-descriptor": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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/expect": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/expect/-/expect-26.6.2.tgz", + "integrity": "sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA==", + "dev": true, + "dependencies": { + "@jest/types": "^26.6.2", + "ansi-styles": "^4.0.0", + "jest-get-type": "^26.3.0", + "jest-matcher-utils": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-regex-util": "^26.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "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/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/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 + "dev": true, + "license": "MIT" }, "node_modules/fast-fifo": { "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", - "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-glob": { "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -3451,9 +5354,8 @@ }, "node_modules/fast-glob/node_modules/glob-parent": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -3463,30 +5365,44 @@ }, "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 + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } }, "node_modules/fastq": { "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, "node_modules/file-entry-cache": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, + "license": "MIT", "dependencies": { "flat-cache": "^4.0.0" }, @@ -3496,9 +5412,8 @@ }, "node_modules/fill-range": { "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -3506,11 +5421,27 @@ "node": ">=8" } }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "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-up": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -3524,18 +5455,16 @@ }, "node_modules/flat": { "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, + "license": "BSD-3-Clause", "bin": { "flat": "cli.js" } }, "node_modules/flat-cache": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, + "license": "MIT", "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" @@ -3546,15 +5475,22 @@ }, "node_modules/flatted": { "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true + "dev": true, + "license": "ISC" + }, + "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/foreground-child": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", "dev": true, + "license": "ISC", "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -3568,9 +5504,8 @@ }, "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, + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -3580,20 +5515,54 @@ "node": ">= 6" } }, + "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/fresh": { "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } }, + "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-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "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 + "dev": true, + "license": "ISC" }, "node_modules/fsevents": { "version": "2.3.3", @@ -3611,36 +5580,68 @@ }, "node_modules/function-bind": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "deprecated": "This package is no longer supported.", + "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/gauge/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/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, + "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, "node_modules/get-func-name": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", "dev": true, + "license": "MIT", "engines": { "node": "*" } }, "node_modules/get-intrinsic": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2", @@ -3655,11 +5656,53 @@ "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": "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/get-stream/node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "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-markdown-css": { "version": "5.5.1", - "resolved": "https://registry.npmjs.org/github-markdown-css/-/github-markdown-css-5.5.1.tgz", - "integrity": "sha512-2osyhNgFt7DEHnGHbgIifWawAqlc68gjJiGwO1xNw/S48jivj8kVaocsVkyJqUi3fm7fdYIDi4C6yOtcqR/aEQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -3669,9 +5712,8 @@ }, "node_modules/glob": { "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -3688,9 +5730,8 @@ }, "node_modules/glob-parent": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -3698,11 +5739,16 @@ "node": ">=10.13.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/node_modules/minimatch": { "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -3712,9 +5758,8 @@ }, "node_modules/globals": { "version": "15.9.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", - "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -3724,9 +5769,8 @@ }, "node_modules/gopd": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dev": true, + "license": "MIT", "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -3734,17 +5778,28 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, "node_modules/graphemer": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/growly": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", + "integrity": "sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw==", + "dev": true, + "optional": true }, "node_modules/gunzip-maybe": { "version": "1.4.2", - "resolved": "https://registry.npmjs.org/gunzip-maybe/-/gunzip-maybe-1.4.2.tgz", - "integrity": "sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==", "dev": true, + "license": "MIT", "dependencies": { "browserify-zlib": "^0.1.4", "is-deflate": "^1.0.0", @@ -3759,18 +5814,16 @@ }, "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, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/has-property-descriptors": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" }, @@ -3780,9 +5833,8 @@ }, "node_modules/has-proto": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -3792,9 +5844,8 @@ }, "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==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -3804,9 +5855,8 @@ }, "node_modules/has-tostringtag": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, + "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" }, @@ -3817,11 +5867,79 @@ "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/hasown": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -3831,18 +5949,40 @@ }, "node_modules/he": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, + "license": "MIT", "bin": { "he": "bin/he" } }, + "node_modules/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/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-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, "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==", "dev": true, + "license": "MIT", "dependencies": { "deep-equal": "~1.0.1", "http-errors": "~1.8.0" @@ -3853,18 +5993,16 @@ }, "node_modules/http-assert/node_modules/depd": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/http-assert/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, + "license": "MIT", "dependencies": { "depd": "~1.1.2", "inherits": "2.0.4", @@ -3878,18 +6016,16 @@ }, "node_modules/http-assert/node_modules/statuses": { "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } }, "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, + "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -3903,9 +6039,8 @@ }, "node_modules/http-proxy-agent": { "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dev": true, + "license": "MIT", "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -3916,9 +6051,8 @@ }, "node_modules/https-proxy-agent": { "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "dev": true, + "license": "MIT", "dependencies": { "agent-base": "^7.0.2", "debug": "4" @@ -3927,20 +6061,39 @@ "node": ">= 14" } }, + "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/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/ignore": { "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } }, "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, + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -3954,9 +6107,8 @@ }, "node_modules/import-in-the-middle": { "version": "1.4.2", - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.4.2.tgz", - "integrity": "sha512-9WOz1Yh/cvO/p69sxRmhyQwrIGGSp7EIdcb+fFNVi7CzQGQB8U1/1XrKVSbEd/GNOAeM0peJtmi7+qphe7NvAw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "acorn": "^8.8.2", "acorn-import-assertions": "^1.9.0", @@ -3964,20 +6116,52 @@ "module-details-from-path": "^1.0.3" } }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "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, + "license": "MIT", "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/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, + "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -3985,15 +6169,40 @@ }, "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, + "license": "ISC" + }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/is-accessor-descriptor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.1.tgz", + "integrity": "sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "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-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, + "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -4001,11 +6210,28 @@ "node": ">=8" } }, + "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-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.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, + "license": "MIT", "dependencies": { "hasown": "^2.0.0" }, @@ -4013,98 +6239,186 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-deflate": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-deflate/-/is-deflate-1.0.0.tgz", - "integrity": "sha512-YDoFpuZWu1VRXlsnlYMzKyVRITXj7Ej/V9gXQ2/pAe7X1J7M/RNOqaIYi6qUn+B7nGyB9pDXrv02dsB58d2ZAQ==", - "dev": true - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/is-data-descriptor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.1.tgz", + "integrity": "sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==", "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/is-deflate": { + "version": "1.0.0", "dev": true, - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "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==", + "node_modules/is-descriptor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.3.tgz", + "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" }, "engines": { "node": ">= 0.4" + } + }, + "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, + "optional": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "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-extglob": "^2.1.1" + "is-plain-object": "^2.0.4" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/is-gzip": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", - "integrity": "sha512-rcfALRIb1YewtnksfRIHGcIY93QnK8BIQ/2c9yDYcG/Y6+vRoJuTWBmmSEbyLLYtXm7q35pHOHbZFQBaLrhlWQ==", + "node_modules/is-extglob": { + "version": "2.1.1", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "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==", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "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, + "engines": { + "node": ">=6" + } + }, + "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-gzip": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } }, "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, + "license": "MIT", "engines": { "node": ">=8" } }, "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, + "license": "MIT", + "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-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-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-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, + "license": "MIT", "engines": { "node": ">=10" }, @@ -4112,1952 +6426,5639 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "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==", + "dev": true, + "optional": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "dev": true, + "license": "ISC" + }, + "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/isomorphic.js": { "version": "0.2.5", - "resolved": "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.2.5.tgz", - "integrity": "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==", "dev": true, + "license": "MIT", "funding": { "type": "GitHub Sponsors ❤", "url": "https://github.com/sponsors/dmonad" } }, - "node_modules/jackspeak": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz", - "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==", + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=8" } }, - "node_modules/jquery": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", - "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==", - "dev": true - }, - "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, - "peer": 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==", + "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": { - "argparse": "^2.0.1" + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=8" } }, - "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/json-schema-compare": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/json-schema-compare/-/json-schema-compare-0.2.2.tgz", - "integrity": "sha512-c4WYmDKyJXhs7WWvAWm3uIYnfyWFoIp+JEoX34rctVvEkMYCPGhXtvmFFXiffBbxfZsvQ0RNnV5H7GvDF5HCqQ==", + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "dependencies": { - "lodash": "^4.17.4" + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/json-schema-merge-allof": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/json-schema-merge-allof/-/json-schema-merge-allof-0.8.1.tgz", - "integrity": "sha512-CTUKmIlPJbsWfzRRnOXz+0MjIqvnleIXwFTzz+t9T86HnYX/Rozria6ZVGLktAU9e+NygNljveP+yxqtQp/Q4w==", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "dependencies": { - "compute-lcm": "^1.1.2", - "json-schema-compare": "^0.2.2", - "lodash": "^4.17.20" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=12.0.0" + "node": ">=10" } }, - "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/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/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, - "bin": { - "json5": "lib/cli.js" + "dependencies": { + "semver": "^7.5.3" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jsonpointer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", - "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "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, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/katex": { - "version": "0.16.10", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.10.tgz", - "integrity": "sha512-ZiqaC04tp2O5utMsl2TEZTXxa6WSC4yo0fv5ML++D3QZv/vx2Mct0mTlRx3O+uUkjfuAgOkzsCmq5MiUEsDDdA==", + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dev": true, - "funding": [ - "https://opencollective.com/katex", - "https://github.com/sponsors/katex" - ], "dependencies": { - "commander": "^8.3.0" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, - "bin": { - "katex": "cli.js" + "engines": { + "node": ">=8" } }, - "node_modules/keygrip": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", - "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", + "node_modules/jackspeak": { + "version": "4.0.2", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { - "tsscmp": "1.0.6" + "@isaacs/cliui": "^8.0.2" }, "engines": { - "node": ">= 0.6" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "node_modules/jest": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest/-/jest-26.6.3.tgz", + "integrity": "sha512-lGS5PXGAzR4RF7V5+XObhqz2KZIDUA1yD0DG6pBVmy10eh0ZIXQImRuzocsI/N2XZ1GrLFwTS27In2i2jlpq1Q==", "dev": true, "dependencies": { - "json-buffer": "3.0.1" + "@jest/core": "^26.6.3", + "import-local": "^3.0.2", + "jest-cli": "^26.6.3" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": ">= 10.14.2" } }, - "node_modules/koa": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/koa/-/koa-2.15.3.tgz", - "integrity": "sha512-j/8tY9j5t+GVMLeioLaxweJiKUayFhlGqNTzf2ZGwL0ZCQijd2RLHK0SLW5Tsko8YyyqCZC2cojIb0/s62qTAg==", + "node_modules/jest-changed-files": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-26.6.2.tgz", + "integrity": "sha512-fDS7szLcY9sCtIip8Fjry9oGf3I2ht/QT21bAHm5Dmf0mD4X3ReNUf17y+bO6fR8WgbIZTlbyG1ak/53cbRzKQ==", "dev": true, "dependencies": { - "accepts": "^1.3.5", - "cache-content-type": "^1.0.0", - "content-disposition": "~0.5.2", - "content-type": "^1.0.4", - "cookies": "~0.9.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" + "@jest/types": "^26.6.2", + "execa": "^4.0.0", + "throat": "^5.0.0" }, "engines": { - "node": "^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4" + "node": ">= 10.14.2" } }, - "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==", - "dev": true - }, - "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==", + "node_modules/jest-cli": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-26.6.3.tgz", + "integrity": "sha512-GF9noBSa9t08pSyl3CY4frMrqp+aQXFGFkf5hEPbh/pIUFYWMK6ZLTfbmadxJVcJrdRoChlWQsA2VkJcDFK8hg==", "dev": true, "dependencies": { - "co": "^4.6.0", - "koa-compose": "^4.1.0" + "@jest/core": "^26.6.3", + "@jest/test-result": "^26.6.2", + "@jest/types": "^26.6.2", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.4", + "import-local": "^3.0.2", + "is-ci": "^2.0.0", + "jest-config": "^26.6.3", + "jest-util": "^26.6.2", + "jest-validate": "^26.6.2", + "prompts": "^2.0.1", + "yargs": "^15.4.1" + }, + "bin": { + "jest": "bin/jest.js" }, "engines": { - "node": ">= 10" + "node": ">= 10.14.2" } }, - "node_modules/koa-morgan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/koa-morgan/-/koa-morgan-1.0.1.tgz", - "integrity": "sha512-JOUdCNlc21G50afBXfErUrr1RKymbgzlrO5KURY+wmDG1Uvd2jmxUJcHgylb/mYXy2SjiNZyYim/ptUBGsIi3A==", + "node_modules/jest-cli/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, - "dependencies": { - "morgan": "^1.6.1" + "engines": { + "node": ">=6" } }, - "node_modules/koa-mount": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/koa-mount/-/koa-mount-4.0.0.tgz", - "integrity": "sha512-rm71jaA/P+6HeCpoRhmCv8KVBIi0tfGuO/dMKicbQnQW/YJntJ6MnnspkodoA4QstMVEZArsCphmd0bJEtoMjQ==", + "node_modules/jest-cli/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, "dependencies": { - "debug": "^4.0.1", - "koa-compose": "^4.1.0" - }, - "engines": { - "node": ">= 7.6.0" - } - }, - "node_modules/koa-send": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/koa-send/-/koa-send-5.0.1.tgz", - "integrity": "sha512-tmcyQ/wXXuxpDxyNXv5yNNkdAMdFRqwtegBXUaowiQzUKqJehttS0x2j0eOZDQAyloAth5w6wwBImnFzkUz3pQ==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "http-errors": "^1.7.3", - "resolve-path": "^1.4.0" - }, - "engines": { - "node": ">= 8" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" } }, - "node_modules/koa-send/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "node_modules/jest-cli/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.6" + "node": ">=0.10.0" } }, - "node_modules/koa-send/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==", + "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, "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">= 0.6" - } - }, - "node_modules/koa-send/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "dev": true, - "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/koa-static": { + "node_modules/jest-cli/node_modules/locate-path": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/koa-static/-/koa-static-5.0.0.tgz", - "integrity": "sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "dependencies": { - "debug": "^3.1.0", - "koa-send": "^5.0.0" + "p-locate": "^4.1.0" }, "engines": { - "node": ">= 7.6.0" + "node": ">=8" } }, - "node_modules/koa-static/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "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, "dependencies": { - "ms": "^2.1.1" + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/koa/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==", + "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, "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" + "p-limit": "^2.2.0" }, "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/koa/node_modules/http-errors/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "node_modules/jest-cli/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": ">= 0.6" + "node": ">=8" } }, - "node_modules/koa/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "node_modules/jest-cli/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/jest-cli/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "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==", + "node_modules/jest-cli/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=6" } }, - "node_modules/lib0": { - "version": "0.2.93", - "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.93.tgz", - "integrity": "sha512-M5IKsiFJYulS+8Eal8f+zAqf5ckm1vffW0fFDxfgxJ+uiVopvDdd3PxJmz0GsVi3YNO7QCFSq0nAsiDmNhLj9Q==", + "node_modules/jest-config": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.6.3.tgz", + "integrity": "sha512-t5qdIj/bCj2j7NFVHb2nFB4aUdfucDn3JRKgrZnplb8nieAirAzRSHP8uDEd+qV6ygzg9Pz4YG7UTJf94LPSyg==", "dev": true, "dependencies": { - "isomorphic.js": "^0.2.4" - }, - "bin": { - "0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js", - "0gentesthtml": "bin/gentesthtml.js", - "0serve": "bin/0serve.js" + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^26.6.3", + "@jest/types": "^26.6.2", + "babel-jest": "^26.6.3", + "chalk": "^4.0.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.4", + "jest-environment-jsdom": "^26.6.2", + "jest-environment-node": "^26.6.2", + "jest-get-type": "^26.3.0", + "jest-jasmine2": "^26.6.3", + "jest-regex-util": "^26.0.0", + "jest-resolve": "^26.6.2", + "jest-util": "^26.6.2", + "jest-validate": "^26.6.2", + "micromatch": "^4.0.2", + "pretty-format": "^26.6.2" + }, + "engines": { + "node": ">= 10.14.2" }, - "engines": { - "node": ">=16" + "peerDependencies": { + "ts-node": ">=9.0.0" }, - "funding": { - "type": "GitHub Sponsors ❤", - "url": "https://github.com/sponsors/dmonad" + "peerDependenciesMeta": { + "ts-node": { + "optional": true + } } }, - "node_modules/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "node_modules/jest-config/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": { - "uc.micro": "^2.0.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "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==", + "node_modules/jest-config/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "dependencies": { - "p-locate": "^5.0.0" + "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": ">=10" + "node": "*" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "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-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", - "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==", + "node_modules/jest-config/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": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=10" + "node": "*" + } + }, + "node_modules/jest-diff": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.2.tgz", + "integrity": "sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^26.6.2", + "jest-get-type": "^26.3.0", + "pretty-format": "^26.6.2" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">= 10.14.2" } }, - "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==", + "node_modules/jest-docblock": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-26.0.0.tgz", + "integrity": "sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w==", "dev": true, - "peer": true, "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" + "detect-newline": "^3.0.0" }, - "bin": { - "loose-envify": "cli.js" + "engines": { + "node": ">= 10.14.2" } }, - "node_modules/loupe": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", - "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "node_modules/jest-each": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.6.2.tgz", + "integrity": "sha512-Mer/f0KaATbjl8MCJ+0GEpNdqmnVmDYqCTJYTvoo7rqmRiDllmp2AYN+06F93nXcY3ur9ShIjS+CO/uD+BbH4A==", "dev": true, "dependencies": { - "get-func-name": "^2.0.1" + "@jest/types": "^26.6.2", + "chalk": "^4.0.0", + "jest-get-type": "^26.3.0", + "jest-util": "^26.6.2", + "pretty-format": "^26.6.2" + }, + "engines": { + "node": ">= 10.14.2" } }, - "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==", + "node_modules/jest-environment-jsdom": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.6.2.tgz", + "integrity": "sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "@jest/environment": "^26.6.2", + "@jest/fake-timers": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "jest-mock": "^26.6.2", + "jest-util": "^26.6.2", + "jsdom": "^16.4.0" }, "engines": { - "node": ">=10" + "node": ">= 10.14.2" } }, - "node_modules/markdown-it": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", - "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "node_modules/jest-environment-node": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.6.2.tgz", + "integrity": "sha512-zhtMio3Exty18dy8ee8eJ9kjnRyZC1N4C1Nt/VShN1apyXc8rWGtJ9lI7vqiWcyyXS4BVSEn9lxAM2D+07/Tag==", "dev": true, "dependencies": { - "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.0", - "mdurl": "^2.0.0", - "punycode.js": "^2.3.1", - "uc.micro": "^2.1.0" + "@jest/environment": "^26.6.2", + "@jest/fake-timers": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "jest-mock": "^26.6.2", + "jest-util": "^26.6.2" }, - "bin": { - "markdown-it": "bin/markdown-it.mjs" + "engines": { + "node": ">= 10.14.2" } }, - "node_modules/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "dev": true + "node_modules/jest-get-type": { + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz", + "integrity": "sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==", + "dev": true, + "engines": { + "node": ">= 10.14.2" + } }, - "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==", + "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": ">= 0.6" + "node": ">= 10.14.2" + }, + "optionalDependencies": { + "fsevents": "^2.1.2" } }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "node_modules/jest-jasmine2": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.6.3.tgz", + "integrity": "sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg==", "dev": true, + "dependencies": { + "@babel/traverse": "^7.1.0", + "@jest/environment": "^26.6.2", + "@jest/source-map": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^26.6.2", + "is-generator-fn": "^2.0.0", + "jest-each": "^26.6.2", + "jest-matcher-utils": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-runtime": "^26.6.3", + "jest-snapshot": "^26.6.2", + "jest-util": "^26.6.2", + "pretty-format": "^26.6.2", + "throat": "^5.0.0" + }, "engines": { - "node": ">= 8" + "node": ">= 10.14.2" } }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "node_modules/jest-leak-detector": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.6.2.tgz", + "integrity": "sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg==", "dev": true, "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" + "jest-get-type": "^26.3.0", + "pretty-format": "^26.6.2" }, "engines": { - "node": ">=8.6" + "node": ">= 10.14.2" } }, - "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==", + "node_modules/jest-matcher-utils": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz", + "integrity": "sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw==", "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^26.6.2", + "jest-get-type": "^26.3.0", + "pretty-format": "^26.6.2" + }, "engines": { - "node": ">= 0.6" + "node": ">= 10.14.2" } }, - "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==", + "node_modules/jest-message-util": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.6.2.tgz", + "integrity": "sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA==", "dev": true, "dependencies": { - "mime-db": "1.52.0" + "@babel/code-frame": "^7.0.0", + "@jest/types": "^26.6.2", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.2", + "pretty-format": "^26.6.2", + "slash": "^3.0.0", + "stack-utils": "^2.0.2" }, "engines": { - "node": ">= 0.6" + "node": ">= 10.14.2" } }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/jest-mock": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.2.tgz", + "integrity": "sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "@jest/types": "^26.6.2", + "@types/node": "*" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">= 10.14.2" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "engines": { + "node": ">=6" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "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, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 10.14.2" } }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "node_modules/jest-resolve": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.6.2.tgz", + "integrity": "sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ==", "dev": true, + "dependencies": { + "@jest/types": "^26.6.2", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^26.6.2", + "read-pkg-up": "^7.0.1", + "resolve": "^1.18.1", + "slash": "^3.0.0" + }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">= 10.14.2" } }, - "node_modules/mocha": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz", - "integrity": "sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA==", + "node_modules/jest-resolve-dependencies": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-26.6.3.tgz", + "integrity": "sha512-pVwUjJkxbhe4RY8QEWzN3vns2kqyuldKpxlxJlzEYfKSvY6/bMvxoFrYYzUO1Gx28yKWN37qyV7rIoIp2h8fTg==", "dev": true, "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "8.1.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" + "@jest/types": "^26.6.2", + "jest-regex-util": "^26.0.0", + "jest-snapshot": "^26.6.2" }, "engines": { - "node": ">= 14.0.0" + "node": ">= 10.14.2" } }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "node_modules/jest-runner": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.6.3.tgz", + "integrity": "sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "@jest/console": "^26.6.2", + "@jest/environment": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.7.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.4", + "jest-config": "^26.6.3", + "jest-docblock": "^26.0.0", + "jest-haste-map": "^26.6.2", + "jest-leak-detector": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-resolve": "^26.6.2", + "jest-runtime": "^26.6.3", + "jest-util": "^26.6.2", + "jest-worker": "^26.6.2", + "source-map-support": "^0.5.6", + "throat": "^5.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/jest-runtime": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.6.3.tgz", + "integrity": "sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw==", + "dev": true, + "dependencies": { + "@jest/console": "^26.6.2", + "@jest/environment": "^26.6.2", + "@jest/fake-timers": "^26.6.2", + "@jest/globals": "^26.6.2", + "@jest/source-map": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/transform": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0", + "cjs-module-lexer": "^0.6.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.4", + "jest-config": "^26.6.3", + "jest-haste-map": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-mock": "^26.6.2", + "jest-regex-util": "^26.0.0", + "jest-resolve": "^26.6.2", + "jest-snapshot": "^26.6.2", + "jest-util": "^26.6.2", + "jest-validate": "^26.6.2", + "slash": "^3.0.0", + "strip-bom": "^4.0.0", + "yargs": "^15.4.1" + }, + "bin": { + "jest-runtime": "bin/jest-runtime.js" }, "engines": { - "node": ">=10" + "node": ">= 10.14.2" } }, - "node_modules/mocha/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/mocha/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==", + "node_modules/jest-runtime/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": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/modern-normalize": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/modern-normalize/-/modern-normalize-2.0.0.tgz", - "integrity": "sha512-CxBoEVKh5U4DH3XuNbc5ONLF6dQBc8dSc7pdZ1957FGbIO5JBqGqqchhET9dTexri8/pk9xBL6+5ceOtCIp1QA==", + "node_modules/jest-runtime/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" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/module-details-from-path": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", - "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==", - "dev": true - }, - "node_modules/monaco-editor": { - "version": "0.44.0", - "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.44.0.tgz", - "integrity": "sha512-5SmjNStN6bSuSE5WPT2ZV+iYn1/yI9sd4Igtk23ChvqB7kDk9lZbB9F5frsuvpB+2njdIeGGFf2G4gbE6rCC9Q==", + "node_modules/jest-runtime/node_modules/cjs-module-lexer": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-0.6.0.tgz", + "integrity": "sha512-uc2Vix1frTfnuzxxu1Hp4ktSvM3QaI4oXl4ZUqL1wjTu/BGki9TrCWoqLTg/drR1KwAEarXuRFCG2Svr1GxPFw==", "dev": true }, - "node_modules/morgan": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", - "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "node_modules/jest-runtime/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "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" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.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==", + "node_modules/jest-runtime/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, - "dependencies": { - "ms": "2.0.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/morgan/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/morgan/node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "node_modules/jest-runtime/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": { - "ee-first": "1.1.1" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">=8" } }, - "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/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==", + "node_modules/jest-runtime/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "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": ">= 0.6" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/node-addon-api": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.0.tgz", - "integrity": "sha512-mNcltoe1R8o7STTegSOHdnJNN7s5EUvhoS7ShnTHDyOSd+8H+UdWODq6qSv67PjC8Zc5JRT8+oLAMCr0SIXw7g==", + "node_modules/jest-runtime/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": "^16 || ^18 || >= 20" + "node": ">=8" } }, - "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==", + "node_modules/jest-runtime/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": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "*" } }, - "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==", + "node_modules/jest-runtime/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": { - "ee-first": "1.1.1" + "p-try": "^2.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/jest-runtime/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": ">= 0.8" + "node": ">=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==", + "node_modules/jest-runtime/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": { - "wrappy": "1" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" } }, - "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/jest-runtime/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/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "node_modules/jest-runtime/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" }, "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "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==", + "node_modules/jest-runtime/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, "dependencies": { - "yocto-queue": "^0.1.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "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": { - "p-limit": "^3.0.2" + "@types/node": "*", + "graceful-fs": "^4.2.4" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 10.14.2" } }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true - }, - "node_modules/pako": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", - "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", - "dev": true - }, - "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==", + "node_modules/jest-snapshot": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.6.2.tgz", + "integrity": "sha512-OLhxz05EzUtsAmOMzuupt1lHYXCNib0ECyuZ/PZOx9TrZcC8vL0x+DUG3TL+GLX3yHG45e6YGjIm0XwDc3q3og==", "dev": true, "dependencies": { - "callsites": "^3.0.0" + "@babel/types": "^7.0.0", + "@jest/types": "^26.6.2", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.0.0", + "chalk": "^4.0.0", + "expect": "^26.6.2", + "graceful-fs": "^4.2.4", + "jest-diff": "^26.6.2", + "jest-get-type": "^26.3.0", + "jest-haste-map": "^26.6.2", + "jest-matcher-utils": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-resolve": "^26.6.2", + "natural-compare": "^1.4.0", + "pretty-format": "^26.6.2", + "semver": "^7.3.2" }, "engines": { - "node": ">=6" - } - }, - "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": ">= 10.14.2" } }, - "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-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "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": ">=8" + "node": ">= 10.14.2" } }, - "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==", + "node_modules/jest-validate": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.6.2.tgz", + "integrity": "sha512-NEYZ9Aeyj0i5rQqbq+tpIOom0YS1u2MVu6+euBsvpgIme+FOfRmoC4R5p0JiAUpaFvFy24xgrpMknarR/93XjQ==", "dev": true, + "dependencies": { + "@jest/types": "^26.6.2", + "camelcase": "^6.0.0", + "chalk": "^4.0.0", + "jest-get-type": "^26.3.0", + "leven": "^3.1.0", + "pretty-format": "^26.6.2" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 10.14.2" } }, - "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==", + "node_modules/jest-watcher": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.6.2.tgz", + "integrity": "sha512-WKJob0P/Em2csiVthsI68p6aGKTIcsfjH9Gsx1f0A3Italz43e3ho0geSAVsmj09RWOELP1AZ/DXyJgOgDKxXQ==", "dev": true, + "dependencies": { + "@jest/test-result": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "jest-util": "^26.6.2", + "string-length": "^4.0.1" + }, "engines": { - "node": ">=8" + "node": ">= 10.14.2" } }, - "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-scurry": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", - "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "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": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" }, "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">= 10.13.0" } }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.1.tgz", - "integrity": "sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ==", + "node_modules/jquery": { + "version": "3.7.1", + "dev": true, + "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/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/@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/jsdom/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/jsdom/node_modules/form-data": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.2.tgz", + "integrity": "sha512-sJe+TQb2vIaIyO783qN6BlMYWMw3WBOHA1Ay2qxsnjuafEOQFJ2JakedOQirT6D5XPRxDvS7AHYyem9fTpb4LQ==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "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==", + "dev": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jsdom/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==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jsdom/node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "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": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "dev": true, + "license": "MIT" + }, + "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-compare": { + "version": "0.2.2", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.4" + } + }, + "node_modules/json-schema-merge-allof": { + "version": "0.8.1", + "dev": true, + "license": "MIT", + "dependencies": { + "compute-lcm": "^1.1.2", + "json-schema-compare": "^0.2.2", + "lodash": "^4.17.20" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "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.3", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/katex": { + "version": "0.16.10", + "dev": true, + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/keygrip": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "tsscmp": "1.0.6" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "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/koa": { + "version": "2.15.3", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "^1.3.5", + "cache-content-type": "^1.0.0", + "content-disposition": "~0.5.2", + "content-type": "^1.0.4", + "cookies": "~0.9.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-compose": { + "version": "4.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/koa-convert": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "co": "^4.6.0", + "koa-compose": "^4.1.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/koa-morgan": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "morgan": "^1.6.1" + } + }, + "node_modules/koa-mount": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.0.1", + "koa-compose": "^4.1.0" + }, + "engines": { + "node": ">= 7.6.0" + } + }, + "node_modules/koa-send": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "http-errors": "^1.7.3", + "resolve-path": "^1.4.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/koa-send/node_modules/depd": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/koa-send/node_modules/http-errors": { + "version": "1.8.1", + "dev": true, + "license": "MIT", + "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/koa-send/node_modules/statuses": { + "version": "1.5.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/koa-static": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.1.0", + "koa-send": "^5.0.0" + }, + "engines": { + "node": ">= 7.6.0" + } + }, + "node_modules/koa-static/node_modules/debug": { + "version": "3.2.7", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/koa/node_modules/http-errors": { + "version": "1.8.1", + "dev": true, + "license": "MIT", + "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/koa/node_modules/http-errors/node_modules/depd": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/koa/node_modules/statuses": { + "version": "1.5.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "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, + "engines": { + "node": ">=6" + } + }, + "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/lib0": { + "version": "0.2.93", + "dev": true, + "license": "MIT", + "dependencies": { + "isomorphic.js": "^0.2.4" + }, + "bin": { + "0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js", + "0gentesthtml": "bin/gentesthtml.js", + "0serve": "bin/0serve.js" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + } + }, + "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/linkify-it": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.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/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "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", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/loupe": { + "version": "2.3.7", + "dev": true, + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "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.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "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/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-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/markdown-it": { + "version": "14.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/mdurl": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "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/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", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "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", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "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/minimatch": { + "version": "9.0.5", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "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-collect/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.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-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.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/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "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": "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/mocha": { + "version": "10.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "8.1.0", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "5.0.1", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/mocha/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/modern-normalize": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/module-details-from-path": { + "version": "1.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/monaco-editor": { + "version": "0.44.0", + "dev": true, + "license": "MIT" + }, + "node_modules/morgan": { + "version": "1.10.0", + "dev": true, + "license": "MIT", + "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", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/morgan/node_modules/ms": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/morgan/node_modules/on-finished": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/nan": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.0.tgz", + "integrity": "sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==", + "dev": true + }, + "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", + "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", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "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/node-addon-api": { + "version": "7.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "^16 || ^18 || >= 20" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "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-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "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 + }, + "node_modules/node-notifier": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.2.tgz", + "integrity": "sha512-oJP/9NAdd9+x2Q+rfphB2RJCHjod70RcRLjosiPMMu5gjIfwVnOUGq2nbTjTUbmy0DJ/tFIVT30+Qe3nzl4TJg==", + "dev": true, + "optional": true, + "dependencies": { + "growly": "^1.3.0", + "is-wsl": "^2.2.0", + "semver": "^7.3.2", + "shellwords": "^0.1.1", + "uuid": "^8.3.0", + "which": "^2.0.2" + } + }, + "node_modules/node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "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/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "deprecated": "This package is no longer supported.", + "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/nwsapi": { + "version": "2.2.13", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.13.tgz", + "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==", + "dev": true + }, + "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==", + "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": "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-descriptor": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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-inspect": { + "version": "1.13.1", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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.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/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", + "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/only": { + "version": "0.0.2", + "dev": true + }, + "node_modules/optionator": { + "version": "0.9.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-each-series": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz", + "integrity": "sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "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-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/package-json-from-dist": { + "version": "1.0.1", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/pako": { + "version": "0.2.9", + "dev": true, + "license": "MIT" + }, + "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", + "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/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", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "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-browserify": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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-scurry": { + "version": "2.0.0", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.0.1", + "dev": true, + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/path-to-regexp": { + "version": "6.3.0", + "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/peek-stream": { + "version": "1.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "duplexify": "^3.5.0", + "through2": "^2.0.3" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "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/playwright": { + "version": "1.47.2", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.47.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.47.2", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/playwright/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/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/preact": { + "version": "10.20.1", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.3.3", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "dev": true, + "dependencies": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/pretty-format/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/process-nextick-args": { + "version": "2.0.1", + "dev": true, + "license": "MIT" + }, + "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/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/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true + }, + "node_modules/pump": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pumpify": { + "version": "1.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.12.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/qsharp-lang": { + "resolved": "npm/qsharp", + "link": true + }, + "node_modules/qsharp-lang-vscode-dev": { + "resolved": "vscode", + "link": true + }, + "node_modules/qsharp-playground": { + "resolved": "playground", + "link": true + }, + "node_modules/querystringify": { + "version": "2.2.0", + "dev": true, + "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/queue-tick": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/randombytes": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/react": { + "version": "18.2.0", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-is": { + "version": "18.2.0", + "dev": true, + "license": "MIT" + }, + "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": "2.3.8", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "dev": true, + "license": "MIT" + }, + "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.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dev": true, + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "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/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", + "dev": true + }, + "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": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "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/require-in-the-middle": { + "version": "7.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=8.6.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", + "dev": true, + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.8", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "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", + "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-from": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-path": { + "version": "1.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "http-errors": "~1.6.2", + "path-is-absolute": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/resolve-path/node_modules/depd": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/resolve-path/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/resolve-path/node_modules/inherits": { + "version": "2.0.3", + "dev": true, + "license": "ISC" + }, + "node_modules/resolve-path/node_modules/setprototypeof": { + "version": "1.1.0", + "dev": true, + "license": "ISC" + }, + "node_modules/resolve-path/node_modules/statuses": { + "version": "1.5.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", + "deprecated": "https://github.com/lydell/resolve-url#deprecated", + "dev": true + }, + "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/reusify": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/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/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "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/rimraf/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/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-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/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/safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==", + "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": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/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/sane/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/sane/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/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": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/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/sane/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/sane/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/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": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "dev": true, + "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": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/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": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "dev": true, + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/sane/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/sane/node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/sane/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/sane/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/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/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": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/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/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/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "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/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/semver": { + "version": "7.6.0", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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/setprototypeof": { + "version": "1.2.0", + "dev": true, + "license": "ISC" + }, + "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/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/shellwords": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", + "dev": true, + "optional": true + }, + "node_modules/shimmer": { + "version": "1.2.1", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/side-channel": { + "version": "1.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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/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": "20 || >=22" + "node": ">=8" + } + }, + "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-descriptor": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "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.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-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/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true + }, + "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.20", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", + "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", + "dev": true + }, + "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": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "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/ssri/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/stack-chain": { + "version": "1.3.7", + "dev": true, + "license": "MIT" + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "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/static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==", + "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-descriptor": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stream-shift": { + "version": "1.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/streamx": { + "version": "2.18.0", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-fifo": "^1.3.2", + "queue-tick": "^1.0.1", + "text-decoder": "^1.1.0" + }, + "optionalDependencies": { + "bare-events": "^2.2.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "dev": true, + "license": "MIT" + }, + "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, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/path-to-regexp": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", - "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", - "dev": true - }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "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": "*" + "node": ">=8" } }, - "node_modules/peek-stream": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/peek-stream/-/peek-stream-1.1.3.tgz", - "integrity": "sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==", + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", "dev": true, + "license": "MIT", "dependencies": { - "buffer-from": "^1.0.0", - "duplexify": "^3.5.0", - "through2": "^2.0.3" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "node_modules/strip-ansi": { + "version": "6.0.1", "dev": true, - "engines": { - "node": ">=8.6" + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "engines": { + "node": ">=8" } }, - "node_modules/playwright": { - "version": "1.47.2", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.2.tgz", - "integrity": "sha512-nx1cLMmQWqmA3UsnjaaokyoUpdVaaDhJhMoxX2qj3McpjnsqFHs516QAKYhqHAgOP+oCFTEOCOAaD1RgD/RQfA==", + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", "dev": true, + "license": "MIT", "dependencies": { - "playwright-core": "1.47.2" - }, - "bin": { - "playwright": "cli.js" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "fsevents": "2.3.2" + "node": ">=8" } }, - "node_modules/playwright-core": { - "version": "1.47.2", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.2.tgz", - "integrity": "sha512-3JvMfF+9LJfe16l7AbSmU555PaTl2tPyQsVInqm3id16pdDfvZ8TTZ/pyzmkbDrZTQefyzU7AIHlZqQnxpqHVQ==", + "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, - "bin": { - "playwright-core": "cli.js" - }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/playwright/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">=0.10.0" } }, - "node_modules/preact": { - "version": "10.20.1", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.20.1.tgz", - "integrity": "sha512-JIFjgFg9B2qnOoGiYMVBtrcFxHqn+dNXbq76bVmcaHYJFYR4lW67AOcXgAYQQTDYXDOg/kTZrKPNCdRgJ2UJmw==", + "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", "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/preact" + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/supports-color": { + "version": "7.2.0", "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "node_modules/prettier": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", - "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", "dev": true, - "bin": { - "prettier": "bin/prettier.cjs" + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" }, "engines": { - "node": ">=14" + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "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/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/pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "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.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar-fs": { + "version": "3.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + }, + "optionalDependencies": { + "bare-fs": "^2.1.1", + "bare-path": "^2.1.0" + } + }, + "node_modules/tar-fs/node_modules/pump": { + "version": "3.0.0", "dev": true, + "license": "MIT", "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==", + "node_modules/tar-stream": { + "version": "3.1.7", "dev": true, + "license": "MIT", "dependencies": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" } }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "dev": true, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/punycode.js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", - "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "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, + "dependencies": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + }, "engines": { - "node": ">=6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/qs": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.0.tgz", - "integrity": "sha512-trVZiI6RMOkO476zLGaBIzszOdFPnCCXHPG9kn0yuS1uz6xdVxPfZdB3vUig9pxPFDM9BRAgz/YUIVQ1/vuiUg==", + "node_modules/terser": { + "version": "5.36.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz", + "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==", "dev": true, "dependencies": { - "side-channel": "^1.0.6" + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" }, "engines": { - "node": ">=0.6" + "node": ">=10" + } + }, + "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": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" } }, - "node_modules/qsharp-lang": { - "resolved": "npm/qsharp", - "link": true - }, - "node_modules/qsharp-lang-vscode-dev": { - "resolved": "vscode", - "link": true - }, - "node_modules/qsharp-playground": { - "resolved": "playground", - "link": true + "node_modules/terser-webpack-plugin/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/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "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/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "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, - "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": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/queue-tick": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", - "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", - "dev": true + "node_modules/test-exclude/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/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "dependencies": { - "safe-buffer": "^5.1.0" + "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/react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "node_modules/test-exclude/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, - "peer": true, "dependencies": { - "loose-envify": "^1.1.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=0.10.0" + "node": "*" } }, - "node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "node_modules/text-decoder": { + "version": "1.1.1", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/throat": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", + "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", "dev": true }, - "node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "node_modules/through2": { + "version": "2.0.5", "dev": true, + "license": "MIT", "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" } }, - "node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "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/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "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": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "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": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", "dev": true, "dependencies": { - "picomatch": "^2.2.1" + "kind-of": "^3.0.2" }, "engines": { - "node": ">=8.10.0" + "node": ">=0.10.0" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "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/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "node_modules/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/require-in-the-middle": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.3.0.tgz", - "integrity": "sha512-nQFEv9gRw6SJAwWD2LrL0NmQvAcO7FBwJbwmr2ttPAacfy0xuiOjE5zt+zM4xDyuyvUaxBi/9gb2SoCyNEVJcw==", + "node_modules/to-regex-range": { + "version": "5.0.1", "dev": true, + "license": "MIT", "dependencies": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" + "is-number": "^7.0.0" }, "engines": { - "node": ">=8.6.0" + "node": ">=8.0" } }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true + "node_modules/toidentifier": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6" + } }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", "dev": true, "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" }, - "bin": { - "resolve": "bin/resolve" + "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==", + "dev": true, + "dependencies": { + "punycode": "^2.1.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=8" } }, - "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==", + "node_modules/ts-api-utils": { + "version": "1.3.0", "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" } }, - "node_modules/resolve-path": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz", - "integrity": "sha512-i1xevIst/Qa+nA9olDxLWnLk8YZbi8R/7JPbCMcgyWaFR6bKWaexgJgEB5oc2PKMjYdrHynyz0NY+if+H98t1w==", + "node_modules/ts-loader": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-8.4.0.tgz", + "integrity": "sha512-6nFY3IZ2//mrPc+ImY3hNWx1vCHyEhl6V+wLmL4CZcm6g1CqX7UKrkc6y0i4FwcfOhxyMPCfaEvh20f4r9GNpw==", "dev": true, "dependencies": { - "http-errors": "~1.6.2", - "path-is-absolute": "1.0.1" + "chalk": "^4.1.0", + "enhanced-resolve": "^4.0.0", + "loader-utils": "^2.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4" }, "engines": { - "node": ">= 0.8" + "node": ">=10.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "*" } }, - "node_modules/resolve-path/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "node_modules/tslib": { + "version": "2.6.2", + "dev": true, + "license": "0BSD" + }, + "node_modules/tsscmp": { + "version": "1.0.6", "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=0.6.x" } }, - "node_modules/resolve-path/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==", + "node_modules/type-check": { + "version": "0.4.0", "dev": true, + "license": "MIT", "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" + "prelude-ls": "^1.2.1" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.8.0" } }, - "node_modules/resolve-path/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/type-detect": { + "version": "4.0.8", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } }, - "node_modules/resolve-path/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/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/resolve-path/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "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/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "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": "5.5.4", "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" + "node": ">=14.17" } }, - "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==", + "node_modules/typescript-eslint": { + "version": "8.3.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" + "@typescript-eslint/eslint-plugin": "8.3.0", + "@typescript-eslint/parser": "8.3.0", + "@typescript-eslint/utils": "8.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "node_modules/uc.micro": { + "version": "2.1.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" + }, + "node_modules/underscore": { + "version": "1.13.6", + "dev": true, + "license": "MIT" }, - "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "node_modules/undici-types": { + "version": "5.26.5", + "dev": true, + "license": "MIT" + }, + "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": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "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==", + "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, - "dependencies": { - "randombytes": "^2.1.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "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": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" + "unique-slug": "^2.0.0" } }, - "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/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==", + "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": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" + "imurmurhash": "^0.1.4" } }, - "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==", + "node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", "dev": true, "engines": { - "node": ">=8" + "node": ">= 4.0.0" } }, - "node_modules/shimmer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", - "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", - "dev": true - }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "node_modules/unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "has-value": "^0.3.1", + "isobject": "^3.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "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, - "engines": { - "node": ">=14" + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/stack-chain": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/stack-chain/-/stack-chain-1.3.7.tgz", - "integrity": "sha512-D8cWtWVdIe/jBA7v5p5Hwl5yOSOrmZPWDPe2KxQ5UAGD+nxbxU0lKXA4h85Ta6+qgdKVL3vUxsbIZjc1kBG7ug==", - "dev": true - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "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.8" + "node": ">=0.10.0" } }, - "node_modules/stream-shift": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", - "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", - "dev": true + "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/streamx": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.18.0.tgz", - "integrity": "sha512-LLUC1TWdjVdn1weXGcSxyTR3T4+acB6tVGXT95y0nGbca4t4o/ng1wKAGTljm9VicuCVLvRlqFYXYy5GwgM7sQ==", + "node_modules/update-browserslist-db": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "fast-fifo": "^1.3.2", - "queue-tick": "^1.0.1", - "text-decoder": "^1.1.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, - "optionalDependencies": { - "bare-events": "^2.2.0" + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.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==", + "node_modules/uri-js": { + "version": "4.4.1", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "safe-buffer": "~5.1.0" + "punycode": "^2.1.0" } }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", + "deprecated": "Please see https://github.com/lydell/urix#deprecated", "dev": true }, - "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==", + "node_modules/url": { + "version": "0.11.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" + "punycode": "^1.4.1", + "qs": "^6.11.2" } }, - "node_modules/string-width-cjs": { - "name": "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==", + "node_modules/url-parse": { + "version": "1.5.10", "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" + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" } }, - "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==", + "node_modules/url/node_modules/punycode": { + "version": "1.4.1", + "dev": true, + "license": "MIT" + }, + "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, - "dependencies": { - "ansi-regex": "^5.0.1" - }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/user-agent-data-types": { + "version": "0.4.2", + "dev": true, + "license": "MIT" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/uuid": { + "version": "8.3.2", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-to-istanbul": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-7.1.2.tgz", + "integrity": "sha512-TxNb7YEUwkLXCQYeudi6lgQ/SZrzNO4kMdlqVxaZPUIUjCv6iSSypUQX70kNBSERpQ8fk48+d61FXk+tgqcWow==", "dev": true, "dependencies": { - "ansi-regex": "^5.0.1" + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" }, "engines": { - "node": ">=8" + "node": ">=10.10.0" } }, - "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==", + "node_modules/v8-to-istanbul/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", "dev": true, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 8" } }, - "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==", + "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": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "node_modules/validate.io-array": { + "version": "1.0.6", "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "license": "MIT" }, - "node_modules/tar-fs": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz", - "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==", + "node_modules/validate.io-function": { + "version": "1.0.2", + "dev": true + }, + "node_modules/validate.io-integer": { + "version": "1.0.5", "dev": true, "dependencies": { - "pump": "^3.0.0", - "tar-stream": "^3.1.5" - }, - "optionalDependencies": { - "bare-fs": "^2.1.1", - "bare-path": "^2.1.0" + "validate.io-number": "^1.0.3" } }, - "node_modules/tar-fs/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==", + "node_modules/validate.io-integer-array": { + "version": "1.0.0", "dev": true, "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "validate.io-array": "^1.0.3", + "validate.io-integer": "^1.0.4" } }, - "node_modules/tar-stream": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", - "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "node_modules/validate.io-number": { + "version": "1.0.3", + "dev": true + }, + "node_modules/vary": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vscode-uri": { + "version": "3.0.8", + "dev": true, + "license": "MIT" + }, + "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==", + "deprecated": "Use your platform's native performance.now() and performance.timeOrigin.", "dev": true, "dependencies": { - "b4a": "^1.6.4", - "fast-fifo": "^1.2.0", - "streamx": "^2.15.0" + "browser-process-hrtime": "^1.0.0" } }, - "node_modules/text-decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.1.1.tgz", - "integrity": "sha512-8zll7REEv4GDD3x4/0pW+ppIxSNs7H1J10IKFZsuOMscumCdM2a+toDGLPA3T+1+fLBql4zbt5z83GEQGGV5VA==", + "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": { - "b4a": "^1.6.4" + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "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==", + "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": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "makeerror": "1.0.12" } }, - "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==", + "node_modules/watchpack": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", "dev": true, "dependencies": { - "is-number": "^7.0.0" + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" }, "engines": { - "node": ">=8.0" + "node": ">=10.13.0" } }, - "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, + "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/webpack": { + "version": "5.95.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.95.0.tgz", + "integrity": "sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.7.1", + "acorn-import-attributes": "^1.9.5", + "browserslist": "^4.21.10", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.1", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "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.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, "engines": { - "node": ">=0.6" + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } } }, - "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "node_modules/webpack-cli": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", + "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", "dev": true, + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^2.1.1", + "@webpack-cli/info": "^2.0.2", + "@webpack-cli/serve": "^2.0.5", + "colorette": "^2.0.14", + "commander": "^10.0.1", + "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, "engines": { - "node": ">=16" + "node": ">=14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "typescript": ">=4.2.0" + "webpack": "5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } } }, - "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true - }, - "node_modules/tsscmp": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", - "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", + "node_modules/webpack-cli/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", "dev": true, "engines": { - "node": ">=0.6.x" + "node": ">=14" } }, - "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==", + "node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", "dev": true, "dependencies": { - "prelude-ls": "^1.2.1" + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=10.0.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==", + "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, - "engines": { - "node": ">=4" + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" } }, - "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==", + "node_modules/webpack/node_modules/enhanced-resolve": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "dev": true, "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" }, "engines": { - "node": ">= 0.6" + "node": ">=10.13.0" } }, - "node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "node_modules/webpack/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, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" }, "engines": { - "node": ">=14.17" + "node": ">=8.0.0" } }, - "node_modules/typescript-eslint": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.3.0.tgz", - "integrity": "sha512-EvWjwWLwwKDIJuBjk2I6UkV8KEQcwZ0VM10nR1rIunRDIP67QJTZAHBXTX0HW/oI1H10YESF8yWie8fRQxjvFA==", + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, - "dependencies": { - "@typescript-eslint/eslint-plugin": "8.3.0", - "@typescript-eslint/parser": "8.3.0", - "@typescript-eslint/utils": "8.3.0" - }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=4.0" } }, - "node_modules/uc.micro": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", - "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "dev": true - }, - "node_modules/underscore": { - "version": "1.13.6", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", - "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", - "dev": true - }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "node_modules/webpack/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": { - "punycode": "^2.1.0" + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" } }, - "node_modules/url": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz", - "integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==", + "node_modules/webpack/node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, "dependencies": { - "punycode": "^1.4.1", - "qs": "^6.11.2" + "randombytes": "^2.1.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==", + "node_modules/webpack/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": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/url/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==", - "dev": true - }, - "node_modules/user-agent-data-types": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/user-agent-data-types/-/user-agent-data-types-0.4.2.tgz", - "integrity": "sha512-jXep3kO/dGNmDOkbDa8ccp4QArgxR4I76m3QVcJ1aOF0B9toc+YtSXtX5gLdDTZXyWlpQYQrABr6L1L2GZOghw==", - "dev": true - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "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==", + "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, - "bin": { - "uuid": "dist/bin/uuid" + "engines": { + "node": ">=6" } }, - "node_modules/validate.io-array": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/validate.io-array/-/validate.io-array-1.0.6.tgz", - "integrity": "sha512-DeOy7CnPEziggrOO5CZhVKJw6S3Yi7e9e65R1Nl/RTN1vTQKnzjfvks0/8kQ40FP/dsjRAOd4hxmJ7uLa6vxkg==", - "dev": true - }, - "node_modules/validate.io-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/validate.io-function/-/validate.io-function-1.0.2.tgz", - "integrity": "sha512-LlFybRJEriSuBnUhQyG5bwglhh50EpTL2ul23MPIuR1odjO7XaMLFV8vHGwp7AZciFxtYOeiSCT5st+XSPONiQ==", - "dev": true - }, - "node_modules/validate.io-integer": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/validate.io-integer/-/validate.io-integer-1.0.5.tgz", - "integrity": "sha512-22izsYSLojN/P6bppBqhgUDjCkr5RY2jd+N2a3DCAUey8ydvrZ/OkGvFPR7qfOpwR2LC5p4Ngzxz36g5Vgr/hQ==", + "node_modules/webpack/node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", "dev": true, "dependencies": { - "validate.io-number": "^1.0.3" + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "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/validate.io-integer-array": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/validate.io-integer-array/-/validate.io-integer-array-1.0.0.tgz", - "integrity": "sha512-mTrMk/1ytQHtCY0oNO3dztafHYyGU88KL+jRxWuzfOmQb+4qqnWmI+gykvGp8usKZOM0H7keJHEbRaFiYA0VrA==", + "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/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": { - "validate.io-array": "^1.0.3", - "validate.io-integer": "^1.0.4" + "iconv-lite": "0.4.24" } }, - "node_modules/validate.io-number": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/validate.io-number/-/validate.io-number-1.0.3.tgz", - "integrity": "sha512-kRAyotcbNaSYoDnXvb4MHg/0a1egJdLwS6oJ38TJY7aw9n93Fl/3blIXdyYvPOp55CNxywooG/3BcrwNrBpcSg==", + "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/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "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": ">= 0.8" + "node": ">=10" } }, - "node_modules/vscode-uri": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", - "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", - "dev": true - }, "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, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -6068,17 +12069,36 @@ "node": ">= 8" } }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "dev": true + }, + "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/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true + }, "node_modules/workerpool": { "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true + "dev": true, + "license": "Apache-2.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==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -6094,9 +12114,8 @@ "node_modules/wrap-ansi-cjs": { "name": "wrap-ansi", "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -6111,15 +12130,31 @@ }, "node_modules/wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/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/write-file-atomic/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/ws": { "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.0.0" }, @@ -6136,20 +12171,30 @@ } } }, + "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/xtend": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.4" } }, "node_modules/y-protocols": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/y-protocols/-/y-protocols-1.0.6.tgz", - "integrity": "sha512-vHRF2L6iT3rwj1jub/K5tYcTT/mEYDUppgNPXwp8fmLpui9f7Yeq3OEtTLVF012j39QnV+KEQpNqoN7CWU7Y9Q==", "dev": true, + "license": "MIT", "dependencies": { "lib0": "^0.2.85" }, @@ -6167,24 +12212,21 @@ }, "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, + "license": "ISC", "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 + "dev": true, + "license": "ISC" }, "node_modules/yargs": { "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -6200,18 +12242,16 @@ }, "node_modules/yargs-parser": { "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/yargs-unparser": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, + "license": "MIT", "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", @@ -6224,9 +12264,8 @@ }, "node_modules/yjs": { "version": "13.6.14", - "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.14.tgz", - "integrity": "sha512-D+7KcUr0j+vBCUSKXXEWfA+bG4UQBviAwP3gYBhkstkgwy5+8diOPMx0iqLIOxNo/HxaREUimZRxqHGAHCL2BQ==", "dev": true, + "license": "MIT", "dependencies": { "lib0": "^0.2.86" }, @@ -6241,18 +12280,16 @@ }, "node_modules/ylru": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.4.0.tgz", - "integrity": "sha512-2OQsPNEmBCvXuFlIni/a+Rn+R2pHW9INm0BxXJ4hVDA8TirqMj+J/Rp9ItLatT/5pZqWwefVrTQcHpixsxnVlA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4.0.0" } }, "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, + "license": "MIT", "engines": { "node": ">=10" }, diff --git a/package.json b/package.json index 7a413bb428..9e0d60f441 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,8 @@ "workspaces": [ "./npm/qsharp", "./playground", - "./vscode" + "./vscode", + "./circuit_vis" ], "license": "MIT", "engines": { @@ -19,7 +20,6 @@ "devDependencies": { "@anywidget/types": "^0.1.4", "@eslint/js": "^9.9.1", - "@microsoft/quantum-viz.js": "^1.0.5", "@parcel/watcher": "^2.4.1", "@types/chai": "^4.3.8", "@types/markdown-it": "^14.1.1", From 99cbdd7728b8e087291c4373e65b2dc58cb11506 Mon Sep 17 00:00:00 2001 From: Mine Starks <16928427+minestarks@users.noreply.github.com> Date: Tue, 29 Oct 2024 21:03:21 +0000 Subject: [PATCH 4/5] remove some unnecessary files --- .prettierignore | 2 + build.py | 6 +- circuit_vis/.gitattributes | 62 - circuit_vis/.github/PULL_REQUEST_TEMPLATE.md | 30 - circuit_vis/.github/workflows/constraints.txt | 5 - circuit_vis/.github/workflows/main.yml | 52 - .../.github/workflows/tests_python.yml | 129 -- circuit_vis/example/circuits.js | 1686 ----------------- circuit_vis/example/index.html | 55 - circuit_vis/example/script.js | 29 - eslint.config.mjs | 1 - 11 files changed, 7 insertions(+), 2050 deletions(-) delete mode 100644 circuit_vis/.gitattributes delete mode 100644 circuit_vis/.github/PULL_REQUEST_TEMPLATE.md delete mode 100644 circuit_vis/.github/workflows/constraints.txt delete mode 100644 circuit_vis/.github/workflows/main.yml delete mode 100644 circuit_vis/.github/workflows/tests_python.yml delete mode 100644 circuit_vis/example/circuits.js delete mode 100644 circuit_vis/example/index.html delete mode 100644 circuit_vis/example/script.js diff --git a/.prettierignore b/.prettierignore index 8cc94b7af4..d62a7667df 100644 --- a/.prettierignore +++ b/.prettierignore @@ -9,6 +9,8 @@ __pycache__/ .vscode-test-web/ .venv/ /allocator/ +/circuit_vis/lib/ +/circuit_vis/dist/ /compiler/ /jupyterlab/lib/ /jupyterlab/qsharp-jupyterlab/labextension/ diff --git a/build.py b/build.py index ec9a6829fc..9c00e1dd93 100755 --- a/build.py +++ b/build.py @@ -386,9 +386,13 @@ def run_ci_historic_benchmark(): npm_args = [npm_cmd, "run", "build:prod"] subprocess.run(npm_args, check=True, text=True, cwd=circuit_vis_src) - step_end() + if run_tests: + step_start("Running the circuit_vis tests") + subprocess.run([npm_cmd, "test"], check=True, text=True, cwd=circuit_vis_src) + step_end() + if build_npm: step_start("Building the npm package") # Copy the wasm build files over for web and node targets diff --git a/circuit_vis/.gitattributes b/circuit_vis/.gitattributes deleted file mode 100644 index 02f83ee3b0..0000000000 --- a/circuit_vis/.gitattributes +++ /dev/null @@ -1,62 +0,0 @@ -############################################################################### -# Set default behavior to automatically normalize line endings. -############################################################################### -* text=auto -*.sh text -*.md text - -############################################################################### -# diff behavior for some non-binary formats -############################################################################### -#*.cs diff=csharp - -############################################################################### -# Set the merge driver for project and solution files -# -# Merging from the command prompt will add diff markers to the files if there -# are conflicts (Merging from VS is not affected by the settings below, in VS -# the diff markers are never inserted). Diff markers may cause the following -# file extensions to fail to load in VS. An alternative would be to treat -# these files as binary and thus will always conflict and require user -# intervention with every merge. To do so, just uncomment the entries below -############################################################################### -#*.sln merge=binary -#*.csproj merge=binary -#*.vbproj merge=binary -#*.vcxproj merge=binary -#*.vcproj merge=binary -#*.dbproj merge=binary -#*.fsproj merge=binary -#*.lsproj merge=binary -#*.wixproj merge=binary -#*.modelproj merge=binary -#*.sqlproj merge=binary -#*.wwaproj merge=binary - -############################################################################### -# behavior for image files -# -# image files are treated as binary by default. -############################################################################### -#*.jpg binary -#*.png binary -#*.gif binary - -############################################################################### -# diff behavior for common document formats -# -# Convert binary document formats to text before diffing them. This feature -# is only available from the command line. Turn it on by uncommenting the -# entries below. -############################################################################### -#*.md diff=astextplain -#*.doc diff=astextplain -#*.DOC diff=astextplain -#*.docx diff=astextplain -#*.DOCX diff=astextplain -#*.dot diff=astextplain -#*.DOT diff=astextplain -#*.pdf diff=astextplain -#*.PDF diff=astextplain -#*.rtf diff=astextplain -#*.RTF diff=astextplain diff --git a/circuit_vis/.github/PULL_REQUEST_TEMPLATE.md b/circuit_vis/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index ad90d6fe5a..0000000000 --- a/circuit_vis/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,30 +0,0 @@ -# Description - -Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. If applicable, include a screenshot that showcase your changes. - -Fixes # (issue) - -## Type of change - -Please delete options that are not relevant. - -- [ ] Bug fix (non-breaking change which fixes an issue) -- [ ] New feature (non-breaking change which adds functionality) -- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) -- [ ] This change requires a documentation update - -# How Has This Been Tested? - -Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration - -- [ ] Test A -- [ ] Test B - -# Checklist: - -- [ ] My code follows the style guidelines of this project -- [ ] I have performed a self-review of my own code -- [ ] I have commented my code, particularly in hard-to-understand areas -- [ ] I have made corresponding changes to the documentation -- [ ] My changes generate no new warnings -- [ ] Any dependent changes have been merged and published in downstream modules diff --git a/circuit_vis/.github/workflows/constraints.txt b/circuit_vis/.github/workflows/constraints.txt deleted file mode 100644 index 7f9f429f19..0000000000 --- a/circuit_vis/.github/workflows/constraints.txt +++ /dev/null @@ -1,5 +0,0 @@ -pip==21.1.3 -nox==2021.6.12 -nox-poetry==0.8.6 -poetry==1.1.7 -virtualenv==20.6.0 diff --git a/circuit_vis/.github/workflows/main.yml b/circuit_vis/.github/workflows/main.yml deleted file mode 100644 index 26eee627dc..0000000000 --- a/circuit_vis/.github/workflows/main.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: CI - -on: - # Triggers the workflow on all PRs and push events to the main branch - pull_request: - push: - branches: [ main ] - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -# Runs jobs in parallel -jobs: - build: - runs-on: ubuntu-latest - - steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v2 - - - name: Install dependencies - run: npm install - - - name: Build TypeScript - run: npm run build - - - name: Build package for production with Webpack - run: npm run build:prod - - test: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - - name: Install dependencies - run: npm install - - - name: Run tests with Jest - run: npm test - - lint: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - - name: Install dependencies - run: npm install - - - name: Lint project with ESLint - run: npm run lint diff --git a/circuit_vis/.github/workflows/tests_python.yml b/circuit_vis/.github/workflows/tests_python.yml deleted file mode 100644 index e446c0598b..0000000000 --- a/circuit_vis/.github/workflows/tests_python.yml +++ /dev/null @@ -1,129 +0,0 @@ -name: Python Tests - -on: - # Triggers the workflow on all PRs and push events to the main branch - pull_request: - push: - branches: [ main ] - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -jobs: - tests: - name: ${{ matrix.session }} ${{ matrix.python-version }} / ${{ matrix.os }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - include: - - { python-version: 3.9, os: ubuntu-latest, session: "pre-commit" } - - { python-version: 3.9, os: ubuntu-latest, session: "flake8" } - - { python-version: 3.9, os: ubuntu-latest, session: "mypy" } - - { python-version: 3.9, os: ubuntu-latest, session: "safety" } - - { python-version: 3.9, os: ubuntu-latest, session: "typeguard" } - - { python-version: 3.9, os: ubuntu-latest, session: "tests" } - - { python-version: 3.8, os: ubuntu-latest, session: "tests" } - - { python-version: 3.9, os: windows-latest, session: "tests" } - - { python-version: 3.9, os: macos-latest, session: "tests" } - - { python-version: 3.9, os: ubuntu-latest, session: "build"} - - env: - NOXSESSION: ${{ matrix.session }} - - steps: - - name: Check out the repository - uses: actions/checkout@v2.3.4 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2.2.2 - with: - python-version: ${{ matrix.python-version }} - - - name: Upgrade pip - run: | - pip install --constraint=.github/workflows/constraints.txt pip - pip --version - - - name: Install Poetry - run: | - pip install --constraint=.github/workflows/constraints.txt poetry - poetry --version - - - name: Install Nox - run: | - pip install --constraint=.github/workflows/constraints.txt nox nox-poetry - nox --version - - - name: Compute pre-commit cache key - if: matrix.session == 'pre-commit' - id: pre-commit-cache - shell: python - run: | - import hashlib - import sys - - python = "py{}.{}".format(*sys.version_info[:2]) - payload = sys.version.encode() + sys.executable.encode() - digest = hashlib.sha256(payload).hexdigest() - result = "${{ runner.os }}-{}-{}-pre-commit".format(python, digest[:8]) - - print("::set-output name=result::{}".format(result)) - - - name: Restore pre-commit cache - uses: actions/cache@v2.1.6 - if: matrix.session == 'pre-commit' - with: - path: ~/.cache/pre-commit - key: ${{ steps.pre-commit-cache.outputs.result }}-${{ hashFiles('.pre-commit-config.yaml') }} - restore-keys: | - ${{ steps.pre-commit-cache.outputs.result }}- - - - name: Run Nox - if: matrix.session != 'build' - run: | - nox --force-color --python=${{ matrix.python-version }} - working-directory: quantum-viz - - - name: Upload coverage data - if: always() && matrix.session == 'tests' - uses: "actions/upload-artifact@v2.2.4" - with: - name: coverage-data - path: "quantum-viz/.coverage.*" - - - name: Combine coverage data and display human readable report - if: always() && matrix.session == 'tests' - run: | - nox --force-color --session=coverage - working-directory: quantum-viz - - - name: Create coverage report - if: always() && matrix.session == 'tests' - run: | - nox --force-color --session=coverage -- xml - working-directory: quantum-viz - - - name: Upload coverage report - if: always() && matrix.session == 'tests' - uses: codecov/codecov-action@v1.5.2 - - - name: Bump version for developmental release - if: "matrix.session == 'build'" - run: | - poetry version patch && - version=$(poetry version | awk '{ print $2 }') && - poetry version $version.dev.$(date +%s) - working-directory: quantum-viz - - - name: Build package - if: matrix.session == 'build' - run: | - poetry build --ansi - working-directory: quantum-viz - - - name: Upload quantum-viz dist - if: matrix.session == 'build' - uses: actions/upload-artifact@v2.2.4 - with: - name: dist - path: quantum-viz/dist/* diff --git a/circuit_vis/example/circuits.js b/circuit_vis/example/circuits.js deleted file mode 100644 index 278218e39e..0000000000 --- a/circuit_vis/example/circuits.js +++ /dev/null @@ -1,1686 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -/* eslint-disable @typescript-eslint/no-unused-vars */ - -// Basic example: entanglement with measurement -//export -const entangle = { - qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], - operations: [ - { - gate: "H", - targets: [{ qId: 0 }], - }, - { - gate: "X", - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - }, - { - gate: "Measure", - isMeasurement: true, - controls: [{ qId: 1 }], - targets: [{ type: 1, qId: 1, cId: 0 }], - }, - ], -}; - -// Sample circuit -//export -const sample = { - qubits: [{ id: 0, numChildren: 1 }, { id: 1 }, { id: 2 }, { id: 3 }], - operations: [ - { - gate: "Foo", - conditionalRender: 3, - targets: [{ qId: 0 }, { qId: 1 }], - children: [ - { - gate: "H", - targets: [{ qId: 1 }], - }, - { - gate: "RX", - displayArgs: "(0.25)", - isControlled: true, - controls: [{ qId: 1 }], - targets: [{ qId: 0 }], - }, - ], - }, - { - gate: "X", - targets: [{ qId: 3 }], - }, - { - gate: "X", - isControlled: true, - controls: [{ qId: 1 }], - targets: [{ qId: 2 }, { qId: 3 }], - }, - { - gate: "X", - isControlled: true, - controls: [{ qId: 2 }, { qId: 3 }], - targets: [{ qId: 1 }], - }, - { - gate: "X", - isControlled: true, - controls: [{ qId: 1 }, { qId: 3 }], - targets: [{ qId: 2 }], - }, - { - gate: "X", - isControlled: true, - controls: [{ qId: 2 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: "measure", - isMeasurement: true, - controls: [{ qId: 0 }], - targets: [{ type: 1, qId: 0, cId: 0 }], - }, - { - gate: "ApplyIfElseR", - isConditional: true, - controls: [{ type: 1, qId: 0, cId: 0 }], - targets: [], - children: [ - { - gate: "H", - targets: [{ qId: 1 }], - conditionalRender: 1, - }, - { - gate: "X", - targets: [{ qId: 1 }], - conditionalRender: 1, - }, - { - gate: "X", - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - conditionalRender: 2, - }, - { - gate: "Foo", - targets: [{ qId: 3 }], - conditionalRender: 2, - }, - ], - }, - { - gate: "SWAP", - targets: [{ qId: 0 }, { qId: 2 }], - children: [ - { - gate: "X", - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 2 }], - }, - { - gate: "X", - isControlled: true, - controls: [{ qId: 2 }], - targets: [{ qId: 0 }], - }, - { - gate: "X", - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 2 }], - }, - ], - }, - { - gate: "ZZ", - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: "ZZ", - targets: [{ qId: 0 }, { qId: 1 }], - }, - { - gate: "XX", - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: "XX", - isControlled: true, - controls: [{ qId: 2 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: "XX", - isControlled: true, - controls: [{ qId: 0 }, { qId: 2 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - ], -}; - -// Teleportation algorithm -//export -const teleport = { - qubits: [ - { - id: 0, - numChildren: 1, - }, - { - id: 1, - numChildren: 1, - }, - { - id: 2, - }, - ], - operations: [ - { - gate: "Teleport", - children: [ - { - gate: "Entangle", - children: [ - { - gate: "H", - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: "X", - isControlled: true, - controls: [ - { - qId: 1, - }, - ], - targets: [ - { - qId: 2, - }, - ], - }, - ], - targets: [ - { - qId: 1, - }, - { - qId: 2, - }, - ], - }, - { - gate: "PrepareMessage", - children: [ - { - gate: "Random", - displayArgs: "([0.5, 0.5])", - children: [ - { - gate: "DrawCategorical", - displayArgs: "([0.5, 0.5])", - children: [ - { - gate: "DrawRandomDouble", - displayArgs: "(0, 1)", - targets: [], - }, - ], - targets: [], - }, - ], - targets: [], - }, - { - gate: "SetPlus", - children: [ - { - gate: "H", - targets: [ - { - qId: 0, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: "Encode", - children: [ - { - gate: "X", - isControlled: true, - controls: [ - { - qId: 0, - }, - ], - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: "H", - targets: [ - { - qId: 0, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - ], - }, - { - gate: "M", - isMeasurement: true, - controls: [ - { - qId: 0, - }, - ], - targets: [ - { - type: 1, - qId: 0, - cId: 0, - }, - ], - }, - { - gate: "measure", - isMeasurement: true, - controls: [ - { - qId: 1, - }, - ], - targets: [ - { - type: 1, - qId: 1, - cId: 0, - }, - ], - }, - { - gate: "Decode", - children: [ - { - gate: "ApplyIfElseR", - isConditional: true, - controls: [ - { - type: 1, - qId: 1, - cId: 0, - }, - ], - targets: [], - children: [ - { - gate: "X", - controls: [ - { - type: 1, - qId: 1, - cId: 0, - }, - ], - targets: [ - { - qId: 2, - }, - ], - conditionalRender: 2, - }, - ], - }, - { - gate: "ApplyIfElseR", - isConditional: true, - controls: [ - { - type: 1, - qId: 0, - cId: 0, - }, - ], - targets: [], - children: [ - { - gate: "Z", - controls: [ - { - type: 1, - qId: 0, - cId: 0, - }, - ], - targets: [ - { - qId: 2, - }, - ], - conditionalRender: 2, - }, - ], - }, - ], - controls: [ - { - type: 1, - qId: 0, - cId: 0, - }, - { - type: 1, - qId: 1, - cId: 0, - }, - ], - targets: [ - { - qId: 2, - }, - ], - }, - ], - targets: [ - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 0, - }, - ], - }, - ], -}; - -// Grover's algorithm -//export -const grover = { - qubits: [ - { - id: 0, - numChildren: 1, - }, - { - id: 1, - numChildren: 1, - }, - { - id: 2, - numChildren: 1, - }, - { - id: 3, - numChildren: 1, - }, - { - id: 4, - }, - ], - operations: [ - { - gate: "GroverSearch", - children: [ - { - gate: "PrepareSuperposition", - children: [ - { - gate: "H", - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: "H", - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: "H", - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: "H", - targets: [ - { - qId: 3, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - }, - { - gate: "GroverIteration", - displayArgs: "(Oracle)", - children: [ - { - gate: "Oracle", - displayArgs: "(Oracle_6)", - children: [ - { - gate: "X", - targets: [ - { - qId: 4, - }, - ], - }, - { - gate: "H", - targets: [ - { - qId: 4, - }, - ], - }, - { - gate: "Oracle_6", - children: [ - { - gate: "X", - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: "X", - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: "X", - isControlled: true, - controls: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - targets: [ - { - qId: 4, - }, - ], - }, - { - gate: "X", - isAdjoint: true, - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: "X", - isAdjoint: true, - targets: [ - { - qId: 0, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - { - qId: 4, - }, - ], - }, - { - gate: "H", - isAdjoint: true, - targets: [ - { - qId: 4, - }, - ], - }, - { - gate: "X", - isAdjoint: true, - targets: [ - { - qId: 4, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - { - qId: 4, - }, - ], - }, - { - gate: "Diffuser", - children: [ - { - gate: "H", - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: "H", - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: "H", - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: "H", - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: "ConditionalPhaseFlip", - children: [ - { - gate: "X", - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: "X", - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: "X", - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: "X", - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: "Z", - isControlled: true, - controls: [ - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: "R", - displayArgs: "(PauliI, 3.141592653589793)", - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: "X", - isAdjoint: true, - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: "X", - isAdjoint: true, - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: "X", - isAdjoint: true, - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: "X", - isAdjoint: true, - targets: [ - { - qId: 0, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - }, - { - gate: "H", - isAdjoint: true, - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: "H", - isAdjoint: true, - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: "H", - isAdjoint: true, - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: "H", - isAdjoint: true, - targets: [ - { - qId: 0, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - { - qId: 4, - }, - ], - }, - { - gate: "GroverIteration", - displayArgs: "(Oracle)", - children: [ - { - gate: "Oracle", - displayArgs: "(Oracle_6)", - children: [ - { - gate: "X", - targets: [ - { - qId: 4, - }, - ], - }, - { - gate: "H", - targets: [ - { - qId: 4, - }, - ], - }, - { - gate: "Oracle_6", - children: [ - { - gate: "X", - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: "X", - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: "X", - isControlled: true, - controls: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - targets: [ - { - qId: 4, - }, - ], - }, - { - gate: "X", - isAdjoint: true, - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: "X", - isAdjoint: true, - targets: [ - { - qId: 0, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - { - qId: 4, - }, - ], - }, - { - gate: "H", - isAdjoint: true, - targets: [ - { - qId: 4, - }, - ], - }, - { - gate: "X", - isAdjoint: true, - targets: [ - { - qId: 4, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - { - qId: 4, - }, - ], - }, - { - gate: "Diffuser", - children: [ - { - gate: "H", - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: "H", - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: "H", - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: "H", - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: "ConditionalPhaseFlip", - children: [ - { - gate: "X", - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: "X", - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: "X", - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: "X", - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: "Z", - isControlled: true, - controls: [ - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: "R", - displayArgs: "(PauliI, 3.141592653589793)", - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: "X", - isAdjoint: true, - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: "X", - isAdjoint: true, - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: "X", - isAdjoint: true, - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: "X", - isAdjoint: true, - targets: [ - { - qId: 0, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - }, - { - gate: "H", - isAdjoint: true, - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: "H", - isAdjoint: true, - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: "H", - isAdjoint: true, - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: "H", - isAdjoint: true, - targets: [ - { - qId: 0, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - { - qId: 4, - }, - ], - }, - { - gate: "GroverIteration", - displayArgs: "(Oracle)", - children: [ - { - gate: "Oracle", - displayArgs: "(Oracle_6)", - children: [ - { - gate: "X", - targets: [ - { - qId: 4, - }, - ], - }, - { - gate: "H", - targets: [ - { - qId: 4, - }, - ], - }, - { - gate: "Oracle_6", - children: [ - { - gate: "X", - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: "X", - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: "X", - isControlled: true, - controls: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - targets: [ - { - qId: 4, - }, - ], - }, - { - gate: "X", - isAdjoint: true, - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: "X", - isAdjoint: true, - targets: [ - { - qId: 0, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - { - qId: 4, - }, - ], - }, - { - gate: "H", - isAdjoint: true, - targets: [ - { - qId: 4, - }, - ], - }, - { - gate: "X", - isAdjoint: true, - targets: [ - { - qId: 4, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - { - qId: 4, - }, - ], - }, - { - gate: "Diffuser", - children: [ - { - gate: "H", - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: "H", - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: "H", - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: "H", - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: "ConditionalPhaseFlip", - children: [ - { - gate: "X", - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: "X", - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: "X", - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: "X", - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: "Z", - isControlled: true, - controls: [ - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: "R", - displayArgs: "(PauliI, 3.141592653589793)", - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: "X", - isAdjoint: true, - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: "X", - isAdjoint: true, - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: "X", - isAdjoint: true, - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: "X", - isAdjoint: true, - targets: [ - { - qId: 0, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - }, - { - gate: "H", - isAdjoint: true, - targets: [ - { - qId: 3, - }, - ], - }, - { - gate: "H", - isAdjoint: true, - targets: [ - { - qId: 2, - }, - ], - }, - { - gate: "H", - isAdjoint: true, - targets: [ - { - qId: 1, - }, - ], - }, - { - gate: "H", - isAdjoint: true, - targets: [ - { - qId: 0, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - { - qId: 4, - }, - ], - }, - { - gate: "M", - isMeasurement: true, - controls: [ - { - qId: 0, - }, - ], - targets: [ - { - type: 1, - qId: 0, - cId: 0, - }, - ], - }, - { - gate: "M", - isMeasurement: true, - controls: [ - { - qId: 1, - }, - ], - targets: [ - { - type: 1, - qId: 1, - cId: 0, - }, - ], - }, - { - gate: "M", - isMeasurement: true, - controls: [ - { - qId: 2, - }, - ], - targets: [ - { - type: 1, - qId: 2, - cId: 0, - }, - ], - }, - { - gate: "M", - isMeasurement: true, - controls: [ - { - qId: 3, - }, - ], - targets: [ - { - type: 1, - qId: 3, - cId: 0, - }, - ], - }, - ], - targets: [ - { - qId: 0, - }, - { - qId: 1, - }, - { - qId: 2, - }, - { - qId: 3, - }, - { - qId: 4, - }, - ], - }, - ], -}; diff --git a/circuit_vis/example/index.html b/circuit_vis/example/index.html deleted file mode 100644 index fb51ec5016..0000000000 --- a/circuit_vis/example/index.html +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - quantum-viz.js Demo - - - - - - - -
-

quantum-viz.js

-
- Please make sure the project is built first by following the - Running from source instructions from the README.md -
- -
-

1. Entangle

-
-

2. Sample

-
-

3. Teleport

-
-

4. Grover

-
-
-
- - diff --git a/circuit_vis/example/script.js b/circuit_vis/example/script.js deleted file mode 100644 index d1c5ff63c4..0000000000 --- a/circuit_vis/example/script.js +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -if (typeof qviz != "undefined") { - document.getElementById("message").remove(); - - /* These examples shows how to draw circuits into containers. */ - const entangleDiv = document.getElementById("entangle"); - if (entangleDiv != null) { - qviz.draw(entangle, entangleDiv, qviz.STYLES["Default"]); - } - - const sampleDiv = document.getElementById("sample"); - if (sampleDiv != null) { - qviz.draw(sample, sampleDiv, qviz.STYLES["Default"]); - } - - const teleportDiv = document.getElementById("teleport"); - if (teleportDiv != null) { - qviz.draw(teleport, teleportDiv, qviz.STYLES["Default"]); - } - - const groverDiv = document.getElementById("grover"); - if (groverDiv != null) { - qviz.draw(grover, groverDiv, qviz.STYLES["Default"]); - } -} else { - document.getElementById("group").remove(); -} diff --git a/eslint.config.mjs b/eslint.config.mjs index 8cb84632ef..e32ba008c8 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -12,7 +12,6 @@ export default tseslint.config( }, { ignores: [ - "circuit_vis/example/", "circuit_vis/lib/", "circuit_vis/coverage/", "circuit_vis/dist/", From 1a934dadcb3b986b9d1dc9c1cf6d7d895580a21a Mon Sep 17 00:00:00 2001 From: Mine Starks <16928427+minestarks@users.noreply.github.com> Date: Tue, 26 Nov 2024 18:19:14 +0000 Subject: [PATCH 5/5] upgrade canvas dep, delete some test code --- circuit_vis/__tests__/process.test.ts | 2877 ------------------------- circuit_vis/__tests__/utils.test.ts | 81 - circuit_vis/package.json | 1 - package-lock.json | 2 +- package.json | 1 + 5 files changed, 2 insertions(+), 2960 deletions(-) delete mode 100644 circuit_vis/__tests__/process.test.ts delete mode 100644 circuit_vis/__tests__/utils.test.ts diff --git a/circuit_vis/__tests__/process.test.ts b/circuit_vis/__tests__/process.test.ts deleted file mode 100644 index ff2931bd11..0000000000 --- a/circuit_vis/__tests__/process.test.ts +++ /dev/null @@ -1,2877 +0,0 @@ -import { Operation, ConditionalRender } from "../src/circuit"; -import { RegisterMap, RegisterType, Register } from "../src/register"; -import { Metadata, GateType } from "../src/metadata"; -import { - processOperations, - _groupOperations, - _alignOps, - _getClassicalRegStart, - _opToMetadata, - _getRegY, - _splitTargetsY, - _fillMetadataX, - _offsetChildrenX, -} from "../src/process"; -import { - minGateWidth, - startX, - startY, - registerHeight, - gatePadding, - classicalRegHeight, - controlBtnOffset, - groupBoxPadding, -} from "../src/constants"; - -describe("Testing _groupOperations", () => { - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, - 3: { type: RegisterType.Qubit, y: startY + registerHeight * 3 }, - }; - test("single qubit gates on 1 qubit register", () => { - const operations: Operation[] = [ - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "Y", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "Z", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([ - [0, 1, 2], - [], - [], - [], - ]); - }); - test("single qubit gates on multiple qubit registers", () => { - const operations: Operation[] = [ - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "Y", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: "Z", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 2 }], - }, - { - gate: "H", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "T", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([ - [0, 3], - [1, 4], - [2], - [], - ]); - }); - test("single and multiple qubit(s) gates", () => { - let operations: Operation[] = [ - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "Y", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: "Z", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([ - [0, 1, 2], - [1], - [], - [], - ]); - operations = [ - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "Y", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "Z", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([ - [0, 1, 2], - [1], - [], - [], - ]); - operations = [ - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "Z", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "Y", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([ - [0, 1, 2], - [2], - [], - [], - ]); - operations = [ - { - gate: "Y", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "Z", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([ - [0, 1, 2], - [0], - [], - [], - ]); - operations = [ - { - gate: "Y", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "Z", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([ - [0, 1], - [0, 2], - [], - [], - ]); - }); - test("multiple qubit gates in ladder format", () => { - const operations: Operation[] = [ - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "Y", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 2 }], - }, - { - gate: "Z", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 2 }], - targets: [{ type: RegisterType.Qubit, qId: 3 }], - }, - { - gate: "H", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 2 }], - targets: [{ type: RegisterType.Qubit, qId: 3 }], - }, - { - gate: "T", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 2 }], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([ - [0, 5], - [0, 1, 4, 5], - [1, 2, 3, 4], - [2, 3], - ]); - }); - test("multiple qubit gates in ladder format with single qubit gate", () => { - let operations: Operation[] = [ - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "Y", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: "Y", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 2 }], - }, - { - gate: "Z", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 2 }], - targets: [{ type: RegisterType.Qubit, qId: 3 }], - }, - { - gate: "Z", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 2 }], - }, - { - gate: "H", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 2 }], - targets: [{ type: RegisterType.Qubit, qId: 3 }], - }, - { - gate: "T", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 2 }], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: "Y", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([ - [0, 8], - [0, 1, 2, 6, 7, 8], - [2, 3, 4, 5, 6], - [3, 5], - ]); - - operations = [ - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "Y", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: "Y", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 2 }], - }, - { - gate: "Z", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 2 }], - }, - { - gate: "T", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 2 }], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: "Y", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: "H", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "H", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "H", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "H", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([ - [0, 6, 7, 8, 9, 10], - [0, 1, 2, 4, 5, 10], - [2, 3, 4], - [], - ]); - }); - test("interleaved multiqubit gates", () => { - let operations: Operation[] = [ - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 3 }], - }, - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [{ type: RegisterType.Qubit, qId: 2 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([ - [1], - [0, 1], - [0, 1], - [0], - ]); - operations = [ - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - ], - targets: [{ type: RegisterType.Qubit, qId: 3 }], - }, - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [ - { type: RegisterType.Qubit, qId: 2 }, - { type: RegisterType.Qubit, qId: 3 }, - ], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([ - [0, 1], - [0, 1], - [0, 1], - [0, 1], - ]); - operations = [ - { - gate: "Foo", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 2 }, - { type: RegisterType.Qubit, qId: 3 }, - ], - }, - { - gate: "Bar", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - { type: RegisterType.Qubit, qId: 2 }, - ], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([ - [0, 1], - [0, 1], - [0, 1], - [0], - ]); - }); - test("classical control gates", () => { - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { - type: RegisterType.Qubit, - y: startY + registerHeight, - children: [ - { - type: RegisterType.Classical, - y: startY + registerHeight + classicalRegHeight, - }, - ], - }, - 2: { - type: RegisterType.Qubit, - y: startY + registerHeight + classicalRegHeight * 2, - children: [ - { - type: RegisterType.Classical, - y: startY + registerHeight + classicalRegHeight * 3, - }, - ], - }, - 3: { - type: RegisterType.Qubit, - y: startY + registerHeight + classicalRegHeight * 4, - }, - }; - let operations: Operation[] = [ - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Classical, qId: 2, cId: 0 }], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([ - [0, 1], - [0], - [0], - [0], - ]); - operations = [ - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Classical, qId: 2, cId: 0 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([ - [0], - [0, 1], - [0], - [0], - ]); - operations = [ - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Classical, qId: 1, cId: 0 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([ - [1], - [0, 1], - [1], - [1], - ]); - }); - test("skipped registers", () => { - let operations: Operation[] = [ - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "Z", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 2 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([[0], [], [1], []]); - operations = [ - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "Z", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 2 }], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([ - [0], - [0, 1], - [1], - [], - ]); - }); - test("no qubits", () => { - const operations: Operation[] = [ - { - gate: "NoOp1", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [], - }, - { - gate: "NoOp2", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [], - }, - ]; - expect(_groupOperations(operations, registers)).toEqual([[], [], [], []]); - }); - test("empty arguments", () => { - expect(_groupOperations([], {})).toEqual([]); - }); -}); - -describe("Testing _alignOps", () => { - test("single qubit gates", () => { - const ops: number[][] = [ - [0, 2, 5, 6], - [1, 3, 4], - ]; - expect(_alignOps(ops)).toEqual(ops); - }); - test("correct ordering of single qubit gate after multiqubit gate", () => { - const ops: number[][] = [ - [0, 1, 3], - [1, 2], - ]; - expect(_alignOps(ops)).toEqual([ - [0, 1, 3], - [null, 1, 2], - ]); - }); - test("padding of multiqubit register after single qubit gate", () => { - const ops: number[][] = [[1], [0, 1]]; - expect(_alignOps(ops)).toEqual([ - [null, 1], - [0, 1], - ]); - }); - test("no padding of single qubit gate after multiqubit gate on different registers", () => { - const ops: number[][] = [[0, 3], [2], [1, 2]]; - expect(_alignOps(ops)).toEqual([ - [0, 3], - [null, 2], - [1, 2], - ]); - }); - test("ladder of cnots", () => { - const ops: number[][] = [ - [0, 4], - [0, 1, 3, 4], - [1, 2, 3], - ]; - expect(_alignOps(ops)).toEqual([ - [0, null, null, null, 4], - [0, 1, null, 3, 4], - [null, 1, 2, 3], - ]); - }); - test("interleaved multiqubit gates", () => { - let ops: number[][] = [[0], [0, 1], [0, 1], [1]]; - expect(_alignOps(ops)).toEqual([[0], [0, 1], [0, 1], [null, 1]]); - ops = [[0], [0], [0, 1], [1], [1], [1]]; - expect(_alignOps(ops)).toEqual([ - [0], - [0], - [0, 1], - [null, 1], - [null, 1], - [null, 1], - ]); - }); - test("skipped registers", () => { - let ops: number[][] = [[0], [], [1], []]; - expect(_alignOps(ops)).toEqual([[0], [], [1], []]); - ops = [[0], [], [1, 2], [2]]; - expect(_alignOps(ops)).toEqual([[0], [], [1, 2], [null, 2]]); - }); - test("no ops", () => { - expect(_alignOps([])).toEqual([]); - }); -}); - -describe("Testing _getClassicalRegStart", () => { - test("no measurement gates", () => { - const ops: Operation[] = [ - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "Y", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ]; - const idxList: number[][] = [[0, 1]]; - expect(_getClassicalRegStart(ops, idxList)).toEqual([]); - }); - test("one measurement gate", () => { - const ops: Operation[] = [ - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "M", - isMeasurement: true, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], - }, - ]; - const idxList: number[][] = [[0, 1]]; - expect(_getClassicalRegStart(ops, idxList)).toEqual([ - [1, { type: RegisterType.Classical, qId: 0, cId: 0 }], - ]); - }); - test("multiple measurement gates", () => { - const ops: Operation[] = [ - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "M", - isMeasurement: true, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Classical, qId: 1, cId: 0 }], - }, - { - gate: "M", - isMeasurement: true, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], - }, - { - gate: "M", - isMeasurement: true, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], - }, - ]; - const idxList: number[][] = [[0, 2, 3], [1]]; - const clsRegs: [number, Register][] = [ - [1, { type: RegisterType.Classical, qId: 0, cId: 0 }], - [2, { type: RegisterType.Classical, qId: 0, cId: 0 }], - [0, { type: RegisterType.Classical, qId: 1, cId: 0 }], - ]; - expect(_getClassicalRegStart(ops, idxList)).toEqual(clsRegs); - }); -}); - -describe("Testing _opToMetadata", () => { - test("single qubit gate", () => { - const op: Operation = { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - }; - const metadata: Metadata = { - type: GateType.X, - x: 0, - controlsY: [], - targetsY: [startY + registerHeight], - label: "X", - width: minGateWidth, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); - test("isAdjoint gate", () => { - const op: Operation = { - gate: "Foo", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: true, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - }; - const metadata: Metadata = { - type: GateType.Unitary, - x: 0, - controlsY: [], - targetsY: [startY + registerHeight], - label: "Foo'", - width: 48, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); - test("measure gate", () => { - const op: Operation = { - gate: "M", - isMeasurement: true, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], - }; - const registers: RegisterMap = { - 0: { - type: RegisterType.Qubit, - y: startY, - children: [ - { type: RegisterType.Classical, y: startY + classicalRegHeight }, - ], - }, - }; - const metadata: Metadata = { - type: GateType.Measure, - x: 0, - controlsY: [startY], - targetsY: [startY + classicalRegHeight], - label: "", - width: minGateWidth, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); - test("swap gate", () => { - const op: Operation = { - gate: "SWAP", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - ], - }; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - }; - const metadata: Metadata = { - type: GateType.Swap, - x: 0, - controlsY: [], - targetsY: [startY, startY + registerHeight], - label: "", - width: minGateWidth, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); - test("isControlled swap gate", () => { - const op: Operation = { - gate: "SWAP", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [ - { type: RegisterType.Qubit, qId: 1 }, - { type: RegisterType.Qubit, qId: 2 }, - ], - }; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, - }; - const metadata: Metadata = { - type: GateType.Swap, - x: 0, - controlsY: [startY], - targetsY: [startY + registerHeight, startY + registerHeight * 2], - label: "", - width: minGateWidth, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); - test("single qubit unitary gate", () => { - const op: Operation = { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - }; - const metadata: Metadata = { - type: GateType.X, - x: 0, - controlsY: [], - targetsY: [startY], - label: "X", - width: minGateWidth, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); - test("multiqubit unitary gate", () => { - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, - }; - let op: Operation = { - gate: "ZZ", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - ], - }; - let metadata: Metadata = { - type: GateType.Unitary, - x: 0, - controlsY: [], - targetsY: [startY, startY + registerHeight], - label: "ZZ", - width: minGateWidth, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - op = { - gate: "XX", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [ - { type: RegisterType.Qubit, qId: 1 }, - { type: RegisterType.Qubit, qId: 2 }, - ], - }; - metadata = { - type: GateType.Unitary, - x: 0, - controlsY: [], - targetsY: [startY + registerHeight, startY + registerHeight * 2], - label: "XX", - width: minGateWidth, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); - test("isControlled unitary gates", () => { - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, - 3: { type: RegisterType.Qubit, y: startY + registerHeight * 3 }, - }; - let op: Operation = { - gate: "ZZ", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }; - let metadata: Metadata = { - type: GateType.ControlledUnitary, - x: 0, - controlsY: [startY + registerHeight], - targetsY: [startY], - label: "ZZ", - width: minGateWidth, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - op = { - gate: "XX", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [ - { type: RegisterType.Qubit, qId: 1 }, - { type: RegisterType.Qubit, qId: 2 }, - ], - }; - metadata = { - type: GateType.ControlledUnitary, - x: 0, - controlsY: [startY], - targetsY: [startY + registerHeight, startY + registerHeight * 2], - label: "XX", - width: minGateWidth, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - op = { - gate: "Foo", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [ - { type: RegisterType.Qubit, qId: 2 }, - { type: RegisterType.Qubit, qId: 3 }, - ], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - ], - }; - metadata = { - type: GateType.ControlledUnitary, - label: "Foo", - x: 0, - controlsY: [startY + registerHeight * 2, startY + registerHeight * 3], - targetsY: [startY, startY + registerHeight], - width: 45, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); - test("single-qubit unitary gates with arguments", () => { - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - }; - let op: Operation = { - gate: "RX", - displayArgs: "(0.25)", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }; - let metadata: Metadata = { - type: GateType.Unitary, - x: 0, - controlsY: [], - targetsY: [startY], - label: "RX", - displayArgs: "(0.25)", - width: 52, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - - // Test long argument - op = { - gate: "RX", - displayArgs: "(0.25, 1.0, 'foobar', (3.14, 6.67))", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }; - metadata = { - type: GateType.Unitary, - x: 0, - controlsY: [], - targetsY: [startY], - label: "RX", - displayArgs: "(0.25, 1.0, 'foobar', (3.14, 6.67))", - width: 188, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - - // Test isControlled - op = { - gate: "RX", - displayArgs: "(0.25)", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }; - metadata = { - type: GateType.ControlledUnitary, - x: 0, - controlsY: [startY + registerHeight], - targetsY: [startY], - label: "RX", - displayArgs: "(0.25)", - width: 52, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); - test("multi-qubit unitary gates with arguments", () => { - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - 2: { type: RegisterType.Qubit, y: startY + registerHeight * 2 }, - }; - let op: Operation = { - gate: "U", - displayArgs: "('foo', 'bar')", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - ], - }; - let metadata: Metadata = { - type: GateType.Unitary, - x: 0, - controlsY: [], - targetsY: [startY, startY + registerHeight], - label: "U", - displayArgs: "('foo', 'bar')", - width: 77, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - - // Test long argument - op = { - gate: "U", - displayArgs: "(0.25, 1.0, 'foobar', (3.14, 6.67))", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - ], - }; - metadata = { - type: GateType.Unitary, - x: 0, - controlsY: [], - targetsY: [startY, startY + registerHeight], - label: "U", - displayArgs: "(0.25, 1.0, 'foobar', (3.14, 6.67))", - width: 188, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - - // Test isControlled - op = { - gate: "U", - displayArgs: "('foo', 'bar')", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 2 }, - ], - }; - metadata = { - type: GateType.ControlledUnitary, - x: 0, - controlsY: [startY + registerHeight], - targetsY: [startY, startY + registerHeight * 2], - label: "U", - displayArgs: "('foo', 'bar')", - width: 77, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); - test("classically-controlled gates", () => { - const op: Operation = { - gate: "X", - isMeasurement: false, - isConditional: true, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - ], - children: [ - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - conditionalRender: ConditionalRender.OnZero, - }, - { - gate: "H", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - conditionalRender: ConditionalRender.OnOne, - }, - ], - }; - const registers: RegisterMap = { - 0: { - type: RegisterType.Qubit, - y: startY, - children: [ - { type: RegisterType.Classical, y: startY + classicalRegHeight }, - ], - }, - 1: { type: RegisterType.Qubit, y: startY + classicalRegHeight * 2 }, - }; - const metadata: Metadata = { - type: GateType.ClassicalControlled, - x: 0, - controlsY: [startY + classicalRegHeight], - targetsY: [startY, startY + classicalRegHeight * 2], - label: "", - width: minGateWidth + controlBtnOffset + groupBoxPadding * 2, - children: [ - [ - { - type: GateType.X, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [startY], - label: "X", - width: minGateWidth, - }, - ], - [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [[startY + classicalRegHeight * 2]], - label: "H", - width: minGateWidth, - }, - ], - ], - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); - test("grouped gates", () => { - const op: Operation = { - gate: "Foo", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - conditionalRender: ConditionalRender.AsGroup, - controls: [], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - ], - children: [ - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - conditionalRender: ConditionalRender.OnZero, - }, - { - gate: "H", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - conditionalRender: ConditionalRender.OnOne, - }, - ], - }; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - }; - const metadata: Metadata = { - type: GateType.Group, - x: 0, - controlsY: [], - targetsY: [startY, startY + registerHeight], - label: "", - width: minGateWidth + groupBoxPadding * 2, - dataAttributes: { expanded: "true" }, - children: [ - { - type: GateType.X, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [startY], - label: "X", - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [[startY + registerHeight]], - label: "H", - width: minGateWidth, - }, - ], - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); - test("no render on null", () => { - const metadata: Metadata = { - type: GateType.Invalid, - x: 0, - controlsY: [], - targetsY: [], - label: "", - width: -1, - }; - expect(_opToMetadata(null, [])).toEqual(metadata); - }); - test("Invalid register", () => { - let op: Operation = { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - }; - expect(() => _opToMetadata(op, registers)).toThrowError( - "ERROR: Qubit register with ID 1 not found.", - ); - - op = { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [{ type: RegisterType.Classical, qId: 0, cId: 2 }], - targets: [], - }; - expect(() => _opToMetadata(op, registers)).toThrowError( - "ERROR: No classical registers found for qubit ID 0.", - ); - }); - test("skipped registers", () => { - const op: Operation = { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 2 }], - }; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 2: { type: RegisterType.Qubit, y: startY + registerHeight }, - }; - const metadata: Metadata = { - type: GateType.X, - x: 0, - controlsY: [], - targetsY: [startY + registerHeight], - label: "X", - width: minGateWidth, - }; - expect(_opToMetadata(op, registers)).toEqual(metadata); - }); -}); - -describe("Testing _getRegY", () => { - const registers: RegisterMap = { - 0: { - type: RegisterType.Qubit, - y: startY, - children: [ - { type: RegisterType.Classical, y: startY + classicalRegHeight }, - ], - }, - }; - test("quantum register", () => { - const reg: Register = { type: RegisterType.Qubit, qId: 0 }; - expect(_getRegY(reg, registers)).toEqual(startY); - }); - test("classical register", () => { - const reg: Register = { type: RegisterType.Classical, qId: 0, cId: 0 }; - expect(_getRegY(reg, registers)).toEqual(startY + classicalRegHeight); - }); - test("No children", () => { - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - }; - const reg: Register = { type: RegisterType.Classical, qId: 0, cId: 0 }; - expect(() => _getRegY(reg, registers)).toThrowError( - "ERROR: No classical registers found for qubit ID 0.", - ); - }); - test("Null cId", () => { - const reg: Register = { type: RegisterType.Classical, qId: 0 }; - expect(() => _getRegY(reg, registers)).toThrowError( - "ERROR: No ID defined for classical register associated with qubit ID 0.", - ); - }); - test("Invalid cId", () => { - const reg: Register = { type: RegisterType.Classical, qId: 0, cId: 1 }; - expect(() => _getRegY(reg, registers)).toThrowError( - "ERROR: Classical register ID 1 invalid for qubit ID 0 with 1 classical register(s).", - ); - }); - test("Invalid register type", () => { - const reg: Register = { type: 2, qId: 0, cId: 1 }; - expect(() => _getRegY(reg, registers)).toThrowError( - "ERROR: Unknown register type 2.", - ); - }); -}); - -describe("Testing _splitTargetsY", () => { - const registers: RegisterMap = { - 0: { - type: RegisterType.Qubit, - y: startY, - }, - 1: { - type: RegisterType.Qubit, - y: startY + registerHeight, - children: [ - { - type: RegisterType.Classical, - y: startY + registerHeight + classicalRegHeight, - }, - ], - }, - 2: { - type: RegisterType.Qubit, - y: startY + registerHeight * 2 + classicalRegHeight, - children: [ - { - type: RegisterType.Classical, - y: startY + registerHeight * 2 + classicalRegHeight * 2, - }, - { - type: RegisterType.Classical, - y: startY + registerHeight * 2 + classicalRegHeight * 3, - }, - { - type: RegisterType.Classical, - y: startY + registerHeight * 2 + classicalRegHeight * 4, - }, - ], - }, - }; - test("adjacent qubit regs", () => { - const targets: Register[] = [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 2 }, - { type: RegisterType.Qubit, qId: 1 }, - ]; - const targetsY: number[] = [ - startY, - startY + registerHeight, - startY + registerHeight * 2 + classicalRegHeight, - ]; - expect(_splitTargetsY(targets, [], registers)).toEqual([targetsY]); - expect(_splitTargetsY(targets, [0], registers)).toEqual([targetsY]); - expect( - _splitTargetsY(targets, [startY + registerHeight * 3], registers), - ).toEqual([targetsY]); - expect( - _splitTargetsY(targets, [0, startY + registerHeight * 3], registers), - ).toEqual([targetsY]); - }); - test("adjacent classical regs", () => { - const targets: Register[] = [ - { type: RegisterType.Classical, qId: 2, cId: 0 }, - { type: RegisterType.Classical, qId: 2, cId: 2 }, - { type: RegisterType.Classical, qId: 2, cId: 1 }, - ]; - const targetsY: number[] = [ - startY + registerHeight * 2 + classicalRegHeight * 2, - startY + registerHeight * 2 + classicalRegHeight * 3, - startY + registerHeight * 2 + classicalRegHeight * 4, - ]; - expect(_splitTargetsY(targets, [], registers)).toEqual([targetsY]); - expect(_splitTargetsY(targets, [0], registers)).toEqual([targetsY]); - expect( - _splitTargetsY( - targets, - [startY + registerHeight * 3 + classicalRegHeight * 4], - registers, - ), - ).toEqual([targetsY]); - expect( - _splitTargetsY( - targets, - [0, startY + registerHeight * 3 + classicalRegHeight * 4], - registers, - ), - ).toEqual([targetsY]); - }); - test("adjacent qubit/classical regs", () => { - const targets: Register[] = [ - { type: RegisterType.Qubit, qId: 2 }, - { type: RegisterType.Classical, qId: 1, cId: 0 }, - { type: RegisterType.Classical, qId: 2, cId: 0 }, - ]; - const targetsY: number[] = [ - startY + registerHeight + classicalRegHeight, - startY + registerHeight * 2 + classicalRegHeight, - startY + registerHeight * 2 + classicalRegHeight * 2, - ]; - expect(_splitTargetsY(targets, [], registers)).toEqual([targetsY]); - expect(_splitTargetsY(targets, [0], registers)).toEqual([targetsY]); - expect( - _splitTargetsY( - targets, - [startY + registerHeight * 3 + classicalRegHeight * 4], - registers, - ), - ).toEqual([targetsY]); - expect( - _splitTargetsY( - targets, - [0, startY + registerHeight * 3 + classicalRegHeight * 4], - registers, - ), - ).toEqual([targetsY]); - }); - test("single target", () => { - const targets: Register[] = [{ type: RegisterType.Qubit, qId: 0 }]; - expect(_splitTargetsY(targets, [], registers)).toEqual([[startY]]); - expect(_splitTargetsY(targets, [0], registers)).toEqual([[startY]]); - expect( - _splitTargetsY(targets, [startY + registerHeight], registers), - ).toEqual([[startY]]); - expect( - _splitTargetsY(targets, [0, startY + registerHeight], registers), - ).toEqual([[startY]]); - }); - test("split non-adjacent qubit regs", () => { - const targets: Register[] = [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 2 }, - ]; - const targetsY: number[][] = [ - [startY], - [startY + registerHeight * 2 + classicalRegHeight], - ]; - expect(_splitTargetsY(targets, [], registers)).toEqual(targetsY); - expect(_splitTargetsY(targets, [0], registers)).toEqual(targetsY); - expect( - _splitTargetsY(targets, [startY + registerHeight * 3], registers), - ).toEqual(targetsY); - expect( - _splitTargetsY(targets, [0, startY + registerHeight * 3], registers), - ).toEqual(targetsY); - }); - test("split two qubit regs with classical register", () => { - const targets: Register[] = [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - ]; - const targetsY: number[][] = [[startY], [startY + registerHeight]]; - expect( - _splitTargetsY(targets, [startY + classicalRegHeight], registers), - ).toEqual(targetsY); - expect( - _splitTargetsY(targets, [0, startY + classicalRegHeight], registers), - ).toEqual(targetsY); - expect( - _splitTargetsY( - targets, - [startY + registerHeight * 2, startY + classicalRegHeight], - registers, - ), - ).toEqual(targetsY); - expect( - _splitTargetsY( - targets, - [startY + registerHeight * 2, 0, startY + classicalRegHeight], - registers, - ), - ).toEqual(targetsY); - }); - test("split two classical regs with classical reg", () => { - const targets: Register[] = [ - { type: RegisterType.Classical, qId: 2, cId: 0 }, - { type: RegisterType.Classical, qId: 2, cId: 2 }, - ]; - const targetsY: number[][] = [ - [startY + registerHeight * 2 + classicalRegHeight * 2], - [startY + registerHeight * 2 + classicalRegHeight * 4], - ]; - expect( - _splitTargetsY( - targets, - [startY + registerHeight * 2 + classicalRegHeight * 3], - registers, - ), - ).toEqual(targetsY); - expect( - _splitTargetsY( - targets, - [0, startY + registerHeight * 2 + classicalRegHeight * 3], - registers, - ), - ).toEqual(targetsY); - expect( - _splitTargetsY( - targets, - [ - startY + registerHeight * 3 + classicalRegHeight * 2, - startY + registerHeight * 2 + classicalRegHeight * 3, - ], - registers, - ), - ).toEqual(targetsY); - expect( - _splitTargetsY( - targets, - [ - startY + registerHeight * 3 + classicalRegHeight * 2, - 0, - startY + registerHeight * 2 + classicalRegHeight * 3, - ], - registers, - ), - ).toEqual(targetsY); - }); - test("split multiple targets with classical register", () => { - const targets: Register[] = [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 2 }, - { type: RegisterType.Qubit, qId: 1 }, - ]; - let targetsY: number[][] = [ - [startY], - [ - startY + registerHeight, - startY + registerHeight * 2 + classicalRegHeight, - ], - ]; - expect( - _splitTargetsY(targets, [startY + classicalRegHeight], registers), - ).toEqual(targetsY); - expect( - _splitTargetsY(targets, [10, startY + classicalRegHeight], registers), - ).toEqual(targetsY); - expect( - _splitTargetsY(targets, [60, startY + classicalRegHeight], registers), - ).toEqual(targetsY); - - targetsY = [ - [startY, startY + registerHeight], - [startY + registerHeight * 2 + classicalRegHeight], - ]; - expect( - _splitTargetsY( - targets, - [startY + registerHeight + classicalRegHeight], - registers, - ), - ).toEqual(targetsY); - }); -}); - -describe("Testing _offsetChildrenX", () => { - const offset = 50; - test("no grandchildren", () => { - const children: Metadata[][] = [ - [ - { - type: GateType.X, - x: 0, - controlsY: [], - targetsY: [], - width: minGateWidth, - label: "X", - }, - ], - ]; - const expected: Metadata[][] = [ - [ - { - type: GateType.X, - x: 50, - controlsY: [], - targetsY: [], - width: minGateWidth, - label: "X", - }, - ], - ]; - _offsetChildrenX(children, offset); - expect(children).toEqual(expected); - }); - test("has grandchildren", () => { - const children: Metadata[][] = [ - [ - { - type: GateType.X, - x: 0, - controlsY: [], - targetsY: [], - width: minGateWidth, - label: "X", - children: [ - [ - { - type: GateType.X, - x: 0, - controlsY: [], - targetsY: [], - width: minGateWidth, - label: "X", - }, - ], - [], - ], - }, - ], - ]; - const expected: Metadata[][] = [ - [ - { - type: GateType.X, - x: 50, - controlsY: [], - targetsY: [], - width: minGateWidth, - label: "X", - children: [ - [ - { - type: GateType.X, - x: 50, - controlsY: [], - targetsY: [], - width: minGateWidth, - label: "X", - }, - ], - [], - ], - }, - ], - ]; - _offsetChildrenX(children, offset); - expect(children).toEqual(expected); - }); - test("undefined child", () => { - expect(() => _offsetChildrenX(undefined, offset)).not.toThrow(); - }); -}); - -describe("Testing _fillMetadataX", () => { - test("Non-classically-isControlled gate", () => { - const columnWidths: number[] = Array(1).fill(minGateWidth); - const expectedEndX = startX + minGateWidth + gatePadding * 2; - const opsMetadata: Metadata[][] = [ - [ - { - type: GateType.X, - x: 0, - controlsY: [], - targetsY: [], - label: "X", - width: minGateWidth, - }, - ], - ]; - const expected: Metadata[][] = [ - [ - { - type: GateType.X, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [], - label: "X", - width: minGateWidth, - }, - ], - ]; - const endX: number = _fillMetadataX(opsMetadata, columnWidths); - expect(opsMetadata).toEqual(expected); - expect(endX).toEqual(expectedEndX); - }); - test("classically-isControlled gate with no children", () => { - const columnWidths: number[] = Array(1).fill(minGateWidth); - const expectedEndX = startX + minGateWidth + gatePadding * 2; - const opsMetadata: Metadata[][] = [ - [ - { - type: GateType.ClassicalControlled, - x: 0, - controlsY: [], - targetsY: [], - label: "X", - width: minGateWidth, - }, - ], - ]; - const expected: Metadata[][] = [ - [ - { - type: GateType.ClassicalControlled, - x: startX, - controlsY: [], - targetsY: [], - label: "X", - width: minGateWidth, - }, - ], - ]; - const endX: number = _fillMetadataX(opsMetadata, columnWidths); - expect(opsMetadata).toEqual(expected); - expect(endX).toEqual(expectedEndX); - }); - test("depth-1 children", () => { - const columnWidths: number[] = Array(1).fill( - minGateWidth + gatePadding * 2, - ); - const expectedEndX = startX + minGateWidth + gatePadding * 4; - const opsMetadata: Metadata[][] = [ - [ - { - type: GateType.ClassicalControlled, - x: 0, - controlsY: [], - targetsY: [], - children: [ - [ - { - type: GateType.X, - x: 0, - controlsY: [], - targetsY: [], - label: "X", - width: minGateWidth, - }, - ], - [ - { - type: GateType.X, - x: 0, - controlsY: [], - targetsY: [], - label: "X", - width: minGateWidth, - }, - ], - ], - label: "X", - width: minGateWidth + controlBtnOffset + groupBoxPadding * 2, - }, - ], - ]; - const expected: Metadata[][] = [ - [ - { - type: GateType.ClassicalControlled, - x: startX, - controlsY: [], - targetsY: [], - children: [ - [ - { - type: GateType.X, - x: controlBtnOffset + groupBoxPadding, - controlsY: [], - targetsY: [], - label: "X", - width: minGateWidth, - }, - ], - [ - { - type: GateType.X, - x: controlBtnOffset + groupBoxPadding, - controlsY: [], - targetsY: [], - label: "X", - width: minGateWidth, - }, - ], - ], - label: "X", - width: minGateWidth + controlBtnOffset + groupBoxPadding * 2, - }, - ], - ]; - - const endX: number = _fillMetadataX(opsMetadata, columnWidths); - expect(opsMetadata).toEqual(expected); - expect(endX).toEqual(expectedEndX); - }); - test("empty args", () => { - const opsMetadata: Metadata[][] = []; - const endX: number = _fillMetadataX(opsMetadata, []); - expect(opsMetadata).toEqual([]); - expect(endX).toEqual(startX); - }); -}); - -describe("Testing processOperations", () => { - test("single qubit gates", () => { - const rxWidth = 52; - const operations: Operation[] = [ - { - gate: "H", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ qId: 0 }], - }, - { - gate: "H", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ qId: 0 }], - }, - { - gate: "H", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ qId: 1 }], - }, - { - gate: "RX", - displayArgs: "(0.25)", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ qId: 1 }], - }, - ]; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - }; - const expectedOps: Metadata[] = [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [[startY]], - label: "H", - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + (minGateWidth + gatePadding * 2) + rxWidth / 2, - controlsY: [], - targetsY: [[startY]], - label: "H", - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [[startY + registerHeight]], - label: "H", - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + (minGateWidth + gatePadding * 2) + rxWidth / 2, - controlsY: [], - targetsY: [[startY + registerHeight]], - label: "RX", - displayArgs: "(0.25)", - width: rxWidth, - }, - ]; - const expectedWidth: number = - startX + minGateWidth + rxWidth + gatePadding * 4; - const { metadataList, svgWidth } = processOperations(operations, registers); - expect(metadataList).toEqual(expectedOps); - expect(svgWidth).toEqual(expectedWidth); - }); - test("single wide qubit gates", () => { - const expectedCustomWidth = 67; - const operations: Operation[] = [ - { - gate: "H", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "FooBar", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "H", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - ]; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - }; - const expectedOps: Metadata[] = [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [[startY]], - label: "H", - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + (minGateWidth + gatePadding * 2) + expectedCustomWidth / 2, - controlsY: [], - targetsY: [[startY]], - label: "FooBar", - width: expectedCustomWidth, - }, - { - type: GateType.Unitary, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [[startY + registerHeight]], - label: "H", - width: minGateWidth, - }, - ]; - const expectedWidth: number = - startX + minGateWidth + expectedCustomWidth + gatePadding * 4; - const { metadataList, svgWidth } = processOperations(operations, registers); - expect(metadataList).toEqual(expectedOps); - expect(svgWidth).toEqual(expectedWidth); - }); - test("single and multi qubit gates", () => { - const operations: Operation[] = [ - { - gate: "H", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 1 }], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "H", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - ]; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - }; - const expectedOps: Metadata[] = [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [[startY]], - label: "H", - width: minGateWidth, - }, - { - type: GateType.Cnot, - x: startX + (minGateWidth + gatePadding * 2) + minGateWidth / 2, - controlsY: [startY + registerHeight], - targetsY: [startY], - label: "X", - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + (minGateWidth + gatePadding * 2) * 2 + minGateWidth / 2, - controlsY: [], - targetsY: [[startY + registerHeight]], - label: "H", - width: minGateWidth, - }, - ]; - const expectedWidth: number = startX + (minGateWidth + gatePadding * 2) * 3; - const { metadataList, svgWidth } = processOperations(operations, registers); - expect(metadataList).toEqual(expectedOps); - expect(svgWidth).toEqual(expectedWidth); - }); - test("classically-controlled gates", () => { - const op: Operation = { - gate: "X", - isMeasurement: false, - isConditional: true, - isControlled: true, - isAdjoint: false, - controls: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - ], - children: [ - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - conditionalRender: ConditionalRender.OnZero, - }, - { - gate: "H", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - conditionalRender: ConditionalRender.OnOne, - }, - { - gate: "Z", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - conditionalRender: ConditionalRender.OnZero, - }, - ], - }; - const registers: RegisterMap = { - 0: { - type: RegisterType.Qubit, - y: startY, - children: [ - { type: RegisterType.Classical, y: startY + classicalRegHeight }, - ], - }, - 1: { type: RegisterType.Qubit, y: startY + classicalRegHeight * 2 }, - }; - const metadata: Metadata = { - type: GateType.ClassicalControlled, - x: startX, - controlsY: [startY + classicalRegHeight], - targetsY: [startY, startY + classicalRegHeight * 2], - label: "", - width: - minGateWidth * 2 + - gatePadding * 2 + - controlBtnOffset + - groupBoxPadding * 2, - children: [ - [ - { - type: GateType.X, - x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, - controlsY: [], - targetsY: [startY], - label: "X", - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: - startX + - minGateWidth + - minGateWidth / 2 + - gatePadding * 2 + - controlBtnOffset + - groupBoxPadding, - controlsY: [], - targetsY: [[startY]], - label: "Z", - width: minGateWidth, - }, - ], - [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2 + controlBtnOffset + groupBoxPadding, - controlsY: [], - targetsY: [[startY + classicalRegHeight * 2]], - label: "H", - width: minGateWidth, - }, - ], - ], - }; - const expectedWidth: number = - startX + - minGateWidth * 2 + - gatePadding * 4 + - controlBtnOffset + - groupBoxPadding * 2; - const { metadataList, svgWidth } = processOperations([op], registers); - expect(metadataList).toEqual([metadata]); - expect(svgWidth).toEqual(expectedWidth); - }); - test("grouped gates", () => { - const op: Operation = { - gate: "Foo", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - ], - conditionalRender: ConditionalRender.AsGroup, - children: [ - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "H", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: "Z", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ], - }; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - }; - const metadata: Metadata = { - type: GateType.Group, - x: startX, - controlsY: [], - targetsY: [startY, startY + registerHeight], - label: "", - width: minGateWidth * 2 + gatePadding * 2 + groupBoxPadding * 2, - dataAttributes: { expanded: "true" }, - children: [ - { - type: GateType.X, - x: startX + minGateWidth / 2 + groupBoxPadding, - controlsY: [], - targetsY: [startY], - label: "X", - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: - startX + - minGateWidth + - minGateWidth / 2 + - gatePadding * 2 + - groupBoxPadding, - controlsY: [], - targetsY: [[startY]], - label: "Z", - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + minGateWidth / 2 + groupBoxPadding, - controlsY: [], - targetsY: [[startY + registerHeight]], - label: "H", - width: minGateWidth, - }, - ], - }; - const expectedWidth: number = - startX + minGateWidth * 2 + gatePadding * 4 + groupBoxPadding * 2; - const { metadataList, svgWidth } = processOperations([op], registers); - expect(metadataList).toEqual([metadata]); - expect(svgWidth).toEqual(expectedWidth); - }); - test("nested grouped gates", () => { - const op: Operation = { - gate: "Foo", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [ - { type: RegisterType.Qubit, qId: 0 }, - { type: RegisterType.Qubit, qId: 1 }, - ], - conditionalRender: ConditionalRender.AsGroup, - children: [ - { - gate: "Foo", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - conditionalRender: ConditionalRender.AsGroup, - children: [ - { - gate: "X", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "Z", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ], - }, - { - gate: "H", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - ], - }; - const registers: RegisterMap = { - 0: { type: RegisterType.Qubit, y: startY }, - 1: { type: RegisterType.Qubit, y: startY + registerHeight }, - }; - const metadata: Metadata = { - type: GateType.Group, - x: startX, - controlsY: [], - targetsY: [startY, startY + registerHeight], - label: "", - width: minGateWidth * 2 + gatePadding * 2 + groupBoxPadding * 4, - dataAttributes: { expanded: "true" }, - children: [ - { - type: GateType.Group, - x: startX + gatePadding, - controlsY: [], - targetsY: [startY], - label: "", - width: minGateWidth * 2 + gatePadding * 2 + groupBoxPadding * 2, - dataAttributes: { expanded: "true" }, - children: [ - { - type: GateType.X, - x: startX + minGateWidth / 2 + groupBoxPadding * 2, - controlsY: [], - targetsY: [startY], - label: "X", - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: - startX + - minGateWidth + - minGateWidth / 2 + - gatePadding * 2 + - groupBoxPadding * 2, - controlsY: [], - targetsY: [[startY]], - label: "Z", - width: minGateWidth, - }, - ], - }, - { - type: GateType.Unitary, - x: startX + minGateWidth + gatePadding + groupBoxPadding * 2, // startX + half of above gate's width + padding - controlsY: [], - targetsY: [[startY + registerHeight]], - label: "H", - width: minGateWidth, - }, - ], - }; - const expectedWidth: number = - startX + minGateWidth * 2 + gatePadding * 4 + groupBoxPadding * 4; - const { metadataList, svgWidth } = processOperations([op], registers); - expect(metadataList).toEqual([metadata]); - expect(svgWidth).toEqual(expectedWidth); - }); - test("measure gates", () => { - const operations: Operation[] = [ - { - gate: "H", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "M", - isMeasurement: true, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [{ type: RegisterType.Classical, qId: 0, cId: 0 }], - }, - { - gate: "H", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 1 }], - }, - { - gate: "M", - isMeasurement: true, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [{ type: RegisterType.Qubit, qId: 0 }], - targets: [{ type: RegisterType.Classical, qId: 0, cId: 1 }], - }, - ]; - const registers: RegisterMap = { - 0: { - type: RegisterType.Qubit, - y: startY, - children: [ - { type: RegisterType.Classical, y: startY + classicalRegHeight }, - { type: RegisterType.Classical, y: startY + classicalRegHeight * 2 }, - ], - }, - 1: { type: RegisterType.Qubit, y: startY + classicalRegHeight * 3 }, - }; - const expectedOps: Metadata[] = [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [[startY]], - label: "H", - width: minGateWidth, - }, - { - type: GateType.Measure, - x: startX + minGateWidth + gatePadding * 2 + minGateWidth / 2, - controlsY: [startY], - targetsY: [startY + classicalRegHeight], - label: "", - width: minGateWidth, - }, - { - type: GateType.Measure, - x: startX + (minGateWidth + gatePadding * 2) * 2 + minGateWidth / 2, - controlsY: [startY], - targetsY: [startY + classicalRegHeight * 2], - label: "", - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [[startY + classicalRegHeight * 3]], - label: "H", - width: minGateWidth, - }, - ]; - const expectedWidth: number = startX + (minGateWidth + gatePadding * 2) * 3; - const { metadataList, svgWidth } = processOperations(operations, registers); - expect(metadataList).toEqual(expectedOps); - expect(svgWidth).toEqual(expectedWidth); - }); - test("skipped registers", () => { - const operations: Operation[] = [ - { - gate: "H", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: "H", - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 2 }], - }, - ]; - const registers: RegisterMap = { - 0: { - type: RegisterType.Qubit, - y: startY, - children: [ - { type: RegisterType.Classical, y: startY + classicalRegHeight }, - { type: RegisterType.Classical, y: startY + classicalRegHeight * 2 }, - ], - }, - 2: { type: RegisterType.Qubit, y: startY + classicalRegHeight * 3 }, - }; - const expectedOps: Metadata[] = [ - { - type: GateType.Unitary, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [[startY]], - label: "H", - width: minGateWidth, - }, - { - type: GateType.Unitary, - x: startX + minGateWidth / 2, - controlsY: [], - targetsY: [[startY + classicalRegHeight * 3]], - label: "H", - width: minGateWidth, - }, - ]; - const expectedWidth: number = startX + minGateWidth + gatePadding * 2; - const { metadataList, svgWidth } = processOperations(operations, registers); - expect(metadataList).toEqual(expectedOps); - expect(svgWidth).toEqual(expectedWidth); - }); - test("no operations", () => { - const operations: Operation[] = []; - const registers: RegisterMap = {}; - const { metadataList, svgWidth } = processOperations(operations, registers); - expect(metadataList).toEqual([]); - expect(svgWidth).toEqual(startX); - }); -}); diff --git a/circuit_vis/__tests__/utils.test.ts b/circuit_vis/__tests__/utils.test.ts deleted file mode 100644 index 1287d67060..0000000000 --- a/circuit_vis/__tests__/utils.test.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { getGateWidth, _getStringWidth, createUUID } from "../src/utils"; -import { minGateWidth, labelPadding } from "../src/constants"; -import { GateType } from "../src/metadata"; - -describe("Testing createUUID", () => { - test("no x in uuid", () => expect(createUUID()).not.toContain("x")); - test("no y in uuid", () => expect(createUUID()).not.toContain("y")); -}); - -describe("Testing getGateWidth", () => { - test("measure gate", () => - expect( - getGateWidth(Object.assign({ type: GateType.Measure, label: "" })), - ).toEqual(minGateWidth)); - test("cnot gate", () => - expect( - getGateWidth(Object.assign({ type: GateType.Cnot, label: "x" })), - ).toEqual(minGateWidth)); - test("swap gate", () => - expect( - getGateWidth(Object.assign({ type: GateType.Swap, label: "" })), - ).toEqual(minGateWidth)); - test("single unitary gate", () => - expect( - getGateWidth(Object.assign({ type: GateType.Unitary, label: "x" })), - ).toEqual(minGateWidth)); - test("multi unitary gate", () => - expect( - getGateWidth(Object.assign({ type: GateType.Unitary, label: "zz" })), - ).toEqual(minGateWidth)); - test("unitary gate with arguments", () => - expect( - getGateWidth( - Object.assign({ - type: GateType.Unitary, - displayArgs: "(0.25)", - label: "RX", - }), - ), - ).toEqual(52)); - test("invalid", () => - expect( - getGateWidth(Object.assign({ type: GateType.Invalid, label: "" })), - ).toEqual(minGateWidth)); - test("unitary with long name", () => - expect( - getGateWidth(Object.assign({ type: GateType.Unitary, label: "FOOBAR" })), - ).toBeCloseTo(59 + labelPadding * 2)); - test("classically controlled gate", () => { - expect( - getGateWidth( - Object.assign({ - type: GateType.ClassicalControlled, - label: "", - width: 500, - }), - ), - ).toEqual(500); - }); -}); - -describe("Testing _getStringWidth", () => { - test("correctly scaled width with font size", () => { - expect(_getStringWidth("FOOBAR", 14)).toEqual(59); - expect(_getStringWidth("FOOBAR", 20)).toEqual(84); - expect(_getStringWidth("FOOBAR", 5)).toEqual(21); - expect(_getStringWidth("FOOBAR", 100)).toEqual(423); - expect(_getStringWidth("FOOBAR", 200)).toEqual(844); - }); - - test("varying size strings", () => { - expect(_getStringWidth("H", 14)).toBeGreaterThanOrEqual(9); - expect(_getStringWidth("H", 14)).toBeLessThanOrEqual(10); - expect( - _getStringWidth("GateWithASuperLongName", 14), - ).toBeGreaterThanOrEqual(174); - expect(_getStringWidth("GateWithASuperLongName", 14)).toBeLessThanOrEqual( - 176, - ); - }); -}); diff --git a/circuit_vis/package.json b/circuit_vis/package.json index 2b14f03b1b..4bc428e53b 100644 --- a/circuit_vis/package.json +++ b/circuit_vis/package.json @@ -33,7 +33,6 @@ "devDependencies": { "@types/jest": "^26.0.4", "@types/prettier": "2.6.0", - "canvas": "^2.6.1", "jest": "^26.6.3", "prettier": "2.6.0", "terser-webpack-plugin": "^4.1.0", diff --git a/package-lock.json b/package-lock.json index d4fea95b2f..a6f45ca7e4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,6 +27,7 @@ "@vscode/extension-telemetry": "^0.8.5", "@vscode/markdown-it-katex": "^1.0.0", "@vscode/test-web": "^0.0.61", + "canvas": "^2.11.2", "chai": "^4.3.10", "esbuild": "^0.23.1", "eslint": "^9.1.0", @@ -57,7 +58,6 @@ "devDependencies": { "@types/jest": "^26.0.4", "@types/prettier": "2.6.0", - "canvas": "^2.6.1", "jest": "^26.6.3", "prettier": "2.6.0", "terser-webpack-plugin": "^4.1.0", diff --git a/package.json b/package.json index 9e0d60f441..0c9f1516e2 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "@vscode/extension-telemetry": "^0.8.5", "@vscode/markdown-it-katex": "^1.0.0", "@vscode/test-web": "^0.0.61", + "canvas": "^2.11.2", "chai": "^4.3.10", "esbuild": "^0.23.1", "eslint": "^9.1.0",