diff --git a/.gitattributes b/.gitattributes index 4cab1f4d2..7898b9e36 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,5 @@ # Set the default behavior, in case people don't have core.autocrlf set. * text=auto + +*.emfatic text +*.treeview text diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 000000000..ce63a07bf --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,36 @@ +name: Documentation + +on: + push: + branches: + - main + tags: "v**" + paths: + - 'docs/**' + - '.github/workflows/docs.yml' + workflow_dispatch: + +jobs: + docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.SDQ_DEV_DEPLOY_TOKEN }} + - uses: actions/checkout@v4 + with: + repository: ${{ github.repository }}.wiki + path: wiki + token: ${{ secrets.SDQ_DEV_DEPLOY_TOKEN }} + + - name: Remove contents in Wiki + working-directory: wiki + run: ls -A1 | grep -v '.git' | xargs rm -r + + - name: Copy Wiki from Docs folder + run: cp -r ./docs/. ./wiki + + - name: Deploy ๐Ÿš€ + uses: stefanzweifel/git-auto-commit-action@v5 + with: + repository: wiki diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index a9ec43e97..9958ac0f4 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -2,8 +2,18 @@ name: Build on: push: + paths: + - ".github/workflows/maven.yml" + - "**/pom.xml" + - "**.java" + - "**.g4" pull_request: types: [opened, synchronize, reopened] + paths: + - ".github/workflows/maven.yml" + - "**/pom.xml" + - "**.java" + - "**.g4" # Allows you to run this workflow manually from the Actions tab workflow_dispatch: @@ -26,7 +36,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK uses: actions/setup-java@v3 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index ca224e041..7f21a6818 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -7,7 +7,7 @@ jobs: publish-maven-central: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-java@v3 with: java-version: '17' @@ -17,7 +17,7 @@ jobs: with: servers: '[{ "id": "ossrh", "username": "jplag", "password": "${{ secrets.OSSRH_TOKEN }}" }]' - name: Import GPG key - uses: crazy-max/ghaction-import-gpg@v5 + uses: crazy-max/ghaction-import-gpg@v6 with: gpg_private_key: ${{ secrets.PGP_SECRET }} passphrase: ${{ secrets.PGP_PW }} @@ -29,7 +29,7 @@ jobs: publish-release-artifact: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-java@v3 with: java-version: '17' diff --git a/.github/workflows/report-viewer-test.yml b/.github/workflows/report-viewer-build-test.yml similarity index 90% rename from .github/workflows/report-viewer-test.yml rename to .github/workflows/report-viewer-build-test.yml index 3093d2457..aa80c86dd 100644 --- a/.github/workflows/report-viewer-test.yml +++ b/.github/workflows/report-viewer-build-test.yml @@ -4,6 +4,9 @@ on: workflow_dispatch: pull_request: types: [opened, synchronize, reopened] + paths: + - ".github/workflows/report-viewer-build-test.yml" + - "report-viewer/**" jobs: pre_job: @@ -23,11 +26,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout ๐Ÿ›Ž๏ธ - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: actions/setup-node@v3 with: - node-version: "16" + node-version: "18" - name: Set version of Report Viewer shell: bash diff --git a/.github/workflows/report-viewer-dev.yml b/.github/workflows/report-viewer-dev.yml index a17775f7f..92fe97407 100644 --- a/.github/workflows/report-viewer-dev.yml +++ b/.github/workflows/report-viewer-dev.yml @@ -5,17 +5,20 @@ on: push: branches: - develop + paths: + - ".github/workflows/report-viewer-dev.yml" + - "report-viewer/**" jobs: build-and-deploy: runs-on: ubuntu-latest steps: - name: Checkout ๐Ÿ›Ž๏ธ - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: actions/setup-node@v3 with: - node-version: "16" + node-version: "18" - name: Set version of Report Viewer shell: bash @@ -34,10 +37,10 @@ jobs: working-directory: report-viewer run: | npm install - npm run build + npm run build-dev - name: Deploy ๐Ÿš€ - uses: JamesIves/github-pages-deploy-action@v4.4.0 + uses: JamesIves/github-pages-deploy-action@v4.4.3 with: branch: gh-pages folder: report-viewer/dist diff --git a/.github/workflows/report-viewer-e2e.yml b/.github/workflows/report-viewer-e2e.yml new file mode 100644 index 000000000..9e265b910 --- /dev/null +++ b/.github/workflows/report-viewer-e2e.yml @@ -0,0 +1,40 @@ +name: Report Viewer e2e Test + +on: + workflow_dispatch: + pull_request: + types: [opened, synchronize, reopened] + paths: + - ".github/workflows/report-viewer-e2e.yml" + - "report-viewer/**" + +jobs: + pre_job: + runs-on: ubuntu-latest + outputs: + should_skip: ${{ steps.skip_check.outputs.should_skip }} + steps: + - id: skip_check + uses: fkirc/skip-duplicate-actions@master + with: + concurrent_skipping: 'same_content_newer' + skip_after_successful_duplicate: 'true' + + test: + needs: pre_job + if: ${{ needs.pre_job.outputs.should_skip != 'true' }} + runs-on: ubuntu-latest + steps: + - name: Checkout ๐Ÿ›Ž๏ธ + uses: actions/checkout@v4 + + - uses: actions/setup-node@v3 + with: + node-version: "18" + + - name: Install and Test ๐Ÿงช + working-directory: report-viewer + run: | + npm install + npx playwright install --with-deps + npm run test:e2e \ No newline at end of file diff --git a/.github/workflows/report-viewer-lint.yml b/.github/workflows/report-viewer-lint.yml new file mode 100644 index 000000000..924b274e7 --- /dev/null +++ b/.github/workflows/report-viewer-lint.yml @@ -0,0 +1,44 @@ +name: Report Viewer ESLint Workflow # Checks linting of report viewer + + +on: + workflow_dispatch: + push: + paths: + - ".github/workflows/report-viewer-lint.yml" + - "report-viewer/**" + pull_request: + types: [opened, synchronize, reopened] + paths: + - ".github/workflows/report-viewer-lint.yml" + - "report-viewer/**" + +jobs: + pre_job: + runs-on: ubuntu-latest + outputs: + should_skip: ${{ steps.skip_check.outputs.should_skip }} + steps: + - id: skip_check + uses: fkirc/skip-duplicate-actions@master + with: + concurrent_skipping: 'same_content_newer' + skip_after_successful_duplicate: 'true' + + check: + needs: pre_job + if: ${{ needs.pre_job.outputs.should_skip != 'true' }} + runs-on: ubuntu-latest + steps: + - name: Checkout ๐Ÿ›Ž๏ธ + uses: actions/checkout@v4 + + - uses: actions/setup-node@v3 + with: + node-version: "18" + + - name: Install and Lint ๐ŸŽจ + working-directory: report-viewer + run: | + npm install + npm run lint diff --git a/.github/workflows/report-viewer-prettier.yml b/.github/workflows/report-viewer-prettier.yml new file mode 100644 index 000000000..e9933c24e --- /dev/null +++ b/.github/workflows/report-viewer-prettier.yml @@ -0,0 +1,45 @@ +name: Report Viewer Prettier Check Workflow # Checks the report viewer against the prettier rules + +on: + workflow_dispatch: + push: + paths: + - ".github/workflows/report-viewer-prettier.yml" + - "report-viewer/**" + pull_request: + types: [opened, synchronize, reopened] + paths: + - ".github/workflows/report-viewer-prettier.yml" + - "report-viewer/**" + + +jobs: + pre_job: + runs-on: ubuntu-latest + outputs: + should_skip: ${{ steps.skip_check.outputs.should_skip }} + steps: + - id: skip_check + uses: fkirc/skip-duplicate-actions@master + with: + concurrent_skipping: 'same_content_newer' + skip_after_successful_duplicate: 'true' + + check: + needs: pre_job + if: ${{ needs.pre_job.outputs.should_skip != 'true' }} + runs-on: ubuntu-latest + steps: + - name: Checkout ๐Ÿ›Ž๏ธ + uses: actions/checkout@v4 + + - uses: actions/setup-node@v3 + with: + node-version: "18" + + - name: Install and Check ๐ŸŽจ + working-directory: report-viewer + run: | + npm install + npx prettier --check src/**/*.ts + npx prettier --check src/**/*.vue diff --git a/.github/workflows/report-viewer-sonarcloud.yml b/.github/workflows/report-viewer-sonarcloud.yml new file mode 100644 index 000000000..4f7231759 --- /dev/null +++ b/.github/workflows/report-viewer-sonarcloud.yml @@ -0,0 +1,35 @@ +name: SonarCloud Scan (ReportViewer) + +on: + push: + branches: + - main + - develop + paths: + - "report-viewer/**" + - ".github/workflows/sonarcloud-report-viewer.yml" + pull_request: + types: [opened, synchronize, reopened] + paths: + - "report-viewer/**" + - ".github/workflows/sonarcloud-report-viewer.yml" + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +jobs: + sonarcloud: + name: SonarCloud + runs-on: ubuntu-latest + if: ${{ github.actor != 'dependabot[bot]' }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + - name: SonarCloud Scan + uses: SonarSource/sonarcloud-github-action@master + with: + projectBaseDir: report-viewer + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN_REPORT_VIEWER }} \ No newline at end of file diff --git a/.github/workflows/report-viewer-unit.yml b/.github/workflows/report-viewer-unit.yml new file mode 100644 index 000000000..48f9082a7 --- /dev/null +++ b/.github/workflows/report-viewer-unit.yml @@ -0,0 +1,39 @@ +name: Report Viewer Unit Test + +on: + workflow_dispatch: + pull_request: + types: [opened, synchronize, reopened] + paths: + - ".github/workflows/report-viewer-unit.yml" + - "report-viewer/**" + +jobs: + pre_job: + runs-on: ubuntu-latest + outputs: + should_skip: ${{ steps.skip_check.outputs.should_skip }} + steps: + - id: skip_check + uses: fkirc/skip-duplicate-actions@master + with: + concurrent_skipping: 'same_content_newer' + skip_after_successful_duplicate: 'true' + + test: + needs: pre_job + if: ${{ needs.pre_job.outputs.should_skip != 'true' }} + runs-on: ubuntu-latest + steps: + - name: Checkout ๐Ÿ›Ž๏ธ + uses: actions/checkout@v4 + + - uses: actions/setup-node@v3 + with: + node-version: "18" + + - name: Install and Test ๐Ÿงช + working-directory: report-viewer + run: | + npm install + npm run test:unit \ No newline at end of file diff --git a/.github/workflows/report-viewer.yml b/.github/workflows/report-viewer.yml index 4393d4ed4..624dde7c5 100644 --- a/.github/workflows/report-viewer.yml +++ b/.github/workflows/report-viewer.yml @@ -11,11 +11,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout ๐Ÿ›Ž๏ธ - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: actions/setup-node@v3 with: - node-version: "16" + node-version: "18" - name: Set version of Report Viewer shell: bash @@ -34,10 +34,10 @@ jobs: working-directory: report-viewer run: | npm install - npm run build + npm run build-prod - name: Deploy ๐Ÿš€ - uses: JamesIves/github-pages-deploy-action@v4.4.0 + uses: JamesIves/github-pages-deploy-action@v4.4.3 with: branch: gh-pages folder: report-viewer/dist diff --git a/.github/workflows/sonarcloud-branch.yml b/.github/workflows/sonarcloud-branch.yml index 93c743268..b257a8101 100644 --- a/.github/workflows/sonarcloud-branch.yml +++ b/.github/workflows/sonarcloud-branch.yml @@ -5,6 +5,11 @@ on: branches: - main - develop + paths: + - ".github/workflows/sonarcloud-branch.yml" + - "**/pom.xml" + - "**.java" + - "**.g4" # Allows you to run this workflow manually from the Actions tab workflow_dispatch: @@ -16,7 +21,7 @@ jobs: if: ${{ github.actor != 'dependabot[bot]' }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - name: Set up JDK diff --git a/.github/workflows/sonarcloud-pr.yml b/.github/workflows/sonarcloud-pr.yml index 360b37dd7..a4274b34f 100644 --- a/.github/workflows/sonarcloud-pr.yml +++ b/.github/workflows/sonarcloud-pr.yml @@ -42,7 +42,7 @@ jobs: needs: get-info steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: ${{ github.event.workflow_run.head_repository.full_name }} ref: ${{ github.event.workflow_run.head_branch }} diff --git a/.github/workflows/spotless.yml b/.github/workflows/spotless.yml index a920d8faf..25de0f0a0 100644 --- a/.github/workflows/spotless.yml +++ b/.github/workflows/spotless.yml @@ -1,9 +1,19 @@ name: Spotless Style Check on: - push: + push: + paths: + - ".github/workflows/spotless.yml" + - "**/pom.xml" + - "**.java" + - "**.g4" pull_request: types: [opened, synchronize, reopened] + paths: + - ".github/workflows/spotless.yml" + - "**/pom.xml" + - "**.java" + - "**.g4" # Allows you to run this workflow manually from the Actions tab workflow_dispatch: @@ -26,7 +36,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK uses: actions/setup-java@v3 diff --git a/.gitignore b/.gitignore index 9db0f9ba9..4c7b782dd 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,8 @@ target/ *.class - +# GitHub +wiki # Mobile Tools for Java (J2ME) .mtj.tmp/ @@ -32,3 +33,6 @@ hs_err_pid* # default result file name, should never be commited result/ result.zip + +# macOS +*.DS_Store diff --git a/README.md b/README.md index 5ecea5808..38f581b8c 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ [![Maven Central](https://maven-badges.herokuapp.com/maven-central/de.jplag/jplag/badge.svg)](https://maven-badges.herokuapp.com/maven-central/de.jplag/jplag) [![License](https://img.shields.io/github/license/jplag/jplag.svg)](https://github.com/jplag/jplag/blob/main/LICENSE) [![GitHub commit activity](https://img.shields.io/github/commit-activity/y/jplag/JPlag)](https://github.com/jplag/JPlag/pulse) +[![SonarCloud Coverage](https://sonarcloud.io/api/project_badges/measure?project=jplag_JPlag&metric=coverage)](https://sonarcloud.io/component_measures/metric/coverage/list?id=jplag_JPlag) [![Report Viewer](https://img.shields.io/badge/report%20viewer-online-b80025)](https://jplag.github.io/JPlag/) [![Java Version](https://img.shields.io/badge/java-SE%2017-yellowgreen)](#download-and-installation) @@ -16,24 +17,27 @@ JPlag is a system that finds similarities among multiple sets of source code fil ## Supported Languages -In the following, a list of all supported languages with their supported language version is provided. A language can be selected from the command line using the `-l ` argument. - -| Language | Version | CLI Argument Name | [state](https://github.com/jplag/JPlag/wiki/2.-Supported-Languages) | parser | -|--------------------------------------------------------|--------:|-------------------|:----------------------------------------------------------------:|:---------:| -| [Java](https://www.java.com) | 17 | java | mature | JavaC | -| [C/C++](https://isocpp.org) | 11 | cpp | legacy | JavaCC | -| [C/C++](https://isocpp.org) | 14 | cpp2 | beta | ANTLR 4 | -| [C#](https://docs.microsoft.com/en-us/dotnet/csharp/) | 8 | csharp | beta | ANTLR 4 | -| [Go](https://go.dev) | 1.17 | golang | beta | ANTLR 4 | -| [Kotlin](https://kotlinlang.org) | 1.3 | kotlin | beta | ANTLR 4 | -| [Python](https://www.python.org) | 3.6 | python3 | legacy | ANTLR 4 | -| [R](https://www.r-project.org/) | 3.5.0 | rlang | beta | ANTLR 4 | -| [Rust](https://www.rust-lang.org/) | 1.60.0 | rust | beta | ANTLR 4 | -| [Scala](https://www.scala-lang.org) | 2.13.8 | scala | beta | Scalameta | -| [Scheme](http://www.scheme-reports.org) | ? | scheme | unknown | JavaCC | -| [Swift](https://www.swift.org) | 5.4 | swift | beta | ANTLR 4 | -| [EMF Metamodel](https://www.eclipse.org/modeling/emf/) | 2.25.0 | emf | alpha | EMF | -| Text (naive) | - | text | legacy | CoreNLP | +In the following, a list of all supported languages with their supported language version is provided. A language can be selected from the command line using subcommands (jplag [jplag options] [language options]). Alternatively you can use the legacy "-l" argument. + +| Language | Version | CLI Argument Name | [state](https://github.com/jplag/JPlag/wiki/2.-Supported-Languages) | parser | +|------------------------------------------------------------|---------------------------------------------------------------------------------------:|-------------------|:-------------------------------------------------------------------:|:---------:| +| [Java](https://www.java.com) | 17 | java | mature | JavaC | +| [C/C++](https://isocpp.org) | 11 | cpp | legacy | JavaCC | +| [C/C++](https://isocpp.org) | 14 | cpp2 | beta | ANTLR 4 | +| [C#](https://docs.microsoft.com/en-us/dotnet/csharp/) | 6 | csharp | beta | ANTLR 4 | +| [Go](https://go.dev) | 1.17 | golang | beta | ANTLR 4 | +| [Kotlin](https://kotlinlang.org) | 1.3 | kotlin | beta | ANTLR 4 | +| [Python](https://www.python.org) | 3.6 | python3 | legacy | ANTLR 4 | +| [R](https://www.r-project.org/) | 3.5.0 | rlang | beta | ANTLR 4 | +| [Rust](https://www.rust-lang.org/) | 1.60.0 | rust | beta | ANTLR 4 | +| [Scala](https://www.scala-lang.org) | 2.13.8 | scala | beta | Scalameta | +| [Scheme](http://www.scheme-reports.org) | ? | scheme | unknown | JavaCC | +| [Swift](https://www.swift.org) | 5.4 | swift | beta | ANTLR 4 | +| [EMF Metamodel](https://www.eclipse.org/modeling/emf/) | 2.25.0 | emf | beta | EMF | +| [EMF Model](https://www.eclipse.org/modeling/emf/) | 2.25.0 | emf-model | alpha | EMF | +| [LLVM IR](https://llvm.org) | 15 | llvmir | beta | ANTLR 4 | +| [TypeScript](https://www.typescriptlang.org/) / JavaScript | [~5](https://github.com/antlr/grammars-v4/tree/master/javascript/typescript/README.md) | typescript | beta | ANTLR 4 | +| Text (naive) | - | text | legacy | CoreNLP | ## Download and Installation You need Java SE 17 to run or build JPlag. @@ -63,43 +67,102 @@ JPlag can either be used via the CLI or directly via its Java API. For more info ### CLI *Note that the [legacy CLI](https://github.com/jplag/jplag/blob/legacy/README.md) is varying slightly.* +The language can either be set with the -l parameter or as a subcommand. If both a subcommand and the -l option are specified, the subcommand will take priority. +When using the subcommand language specific arguments can be set. +A list of language specific options can be obtained by requesting the help page of a subcommand (e.g. "jplag java -h"). + ``` -positional arguments: - rootDir Root-directory with submissions to check for plagiarism - -named arguments: - -h, --help show this help message and exit - -new NEW [NEW ...] Root-directory with submissions to check for plagiarism (same as the root directory) - -old OLD [OLD ...] Root-directory with prior submissions to compare against - -l {cpp,csharp,emf,go,java,kotlin,python3,rlang,rust,scala,scheme,swift,text} - Select the language to parse the submissions (default: java) - -bc BC Path of the directory containing the base code (common framework used in all - submissions) - -t T Tunes the comparison sensitivity by adjusting the minimum token required to be counted - as a matching section. A smaller increases the sensitivity but might lead to more - false-positives - -n N The maximum number of comparisons that will be shown in the generated report, if set - to -1 all comparisons will be shown (default: 100) - -r R Name of the directory in which the comparison results will be stored (default: result) - -Advanced: - -d Debug parser. Non-parsable files will be stored (default: false) - -s S Look in directories /*/ for programs - -p P comma-separated list of all filename suffixes that are included - -x X All files named in this file will be ignored in the comparison (line-separated list) - -m M Comparison similarity threshold [0.0-1.0]: All comparisons above this threshold will - be saved (default: 0.0) - -Clustering: - --cluster-skip Skips the clustering (default: false) - --cluster-alg {AGGLOMERATIVE,SPECTRAL} - Which clustering algorithm to use. Agglomerative merges similar submissions bottom up. - Spectral clustering is combined with Bayesian Optimization to execute the k-Means - clustering algorithm multiple times, hopefully finding a "good" clustering +Usage: jplag [OPTIONS] [root-dirs[,root-dirs...]...] [COMMAND] + + [root-dirs[,root-dirs...]...] + Root-directory with submissions to check for plagiarism + + -bc, --bc, --base-code= + Path of the directory containing the base code + (common framework used in all submissions) + + -h, --help display this help and exit + -l, --language= + Select the language to parse the submissions (default: + java). The language names are the same as the + subcommands. + + -n, --shown-comparisons= + The maximum number of comparisons that will be shown + in the generated report, if set to -1 all comparisons + will be shown (default: 100) + + -new, --new=[,...] + Root-directory with submissions to check for plagiarism + (same as the root directory) + + -old, --old=[,...] + Root-directory with prior submissions to compare against + + -r, --result-directory= + Name of the directory in which the comparison results + will be stored (default: result) + + -t, --min-tokens= + Tunes the comparison sensitivity by adjusting the + minimum token required to be counted as a matching + section. A smaller increases the sensitivity but + might lead to more false-positives + +Advanced + -d, --debug Debug parser. Non-parsable files will be stored + (default: false) + + -m, --similarity-threshold= + Comparison similarity threshold [0.0-1.0]: All + comparisons above this threshold will be saved + (default: 0.0) + + -p, --suffixes=[,...] + comma-separated list of all filename suffixes that are + included + + -s, --subdirectory= + Look in directories /*/ for programs + + -x, --exclusion-file= + All files named in this file will be ignored in the + comparison (line-separated list) + +Clustering + --cluster-alg, --cluster-algorithm= + Which clustering algorithm to use. Agglomerative merges + similar submissions bottom up. Spectral clustering is + combined with Bayesian Optimization to execute + the k-Means clustering algorithm multiple times, + hopefully finding a "good" clustering automatically. (default: spectral) - --cluster-metric {AVG,MIN,MAX,INTERSECTION} - The metric used for clustering. AVG is intersection over union, MAX can expose some - attempts of obfuscation. (default: MAX) + + --cluster-metric= + The metric used for clustering. AVG is intersection + over union, MAX can expose some attempts of + obfuscation. (default: MAX) + + --cluster-skip Skips the clustering (default: false) +Commands: + cpp + cpp2 + csharp + emf + emf-model + go + java + kotlin + llvmir + python3 + rlang + rust + scala + scheme + scxml + swift + text + typescript ``` ### Java API @@ -109,14 +172,14 @@ The new API makes it easy to integrate JPlag's plagiarism detection into externa ```java -Language language = new de.jplag.java.Language(); +JavaLanguage language = new JavaLanguage(); +language.getOptions(); //Use the object returned by this to set language options(same as language specific arguments above). Set submissionDirectories = Set.of(new File("/path/to/rootDir")); File baseCode = new File("/path/to/baseCode"); JPlagOptions options = new JPlagOptions(language, submissionDirectories, Set.of()).withBaseCodeSubmissionDirectory(baseCode); -JPlag jplag = new JPlag(options); try { - JPlagResult result = jplag.run(); + JPlagResult result = JPlag.run(options); // Optional ReportObjectFactory reportObjectFactory = new ReportObjectFactory(); diff --git a/cli/pom.xml b/cli/pom.xml index 791736d02..b6812a3eb 100644 --- a/cli/pom.xml +++ b/cli/pom.xml @@ -82,6 +82,11 @@ scheme ${revision} + + de.jplag + scxml + ${revision} + de.jplag swift @@ -92,6 +97,21 @@ emf-metamodel ${revision} + + de.jplag + emf-model + ${revision} + + + de.jplag + typescript + ${revision} + + + de.jplag + llvmir + ${revision} + org.kohsuke.metainf-services @@ -99,8 +119,9 @@ - net.sourceforge.argparse4j - argparse4j + info.picocli + picocli + 4.7.5 diff --git a/cli/src/main/java/de/jplag/cli/CLI.java b/cli/src/main/java/de/jplag/cli/CLI.java index 3694b474e..9507a9a80 100644 --- a/cli/src/main/java/de/jplag/cli/CLI.java +++ b/cli/src/main/java/de/jplag/cli/CLI.java @@ -1,39 +1,15 @@ package de.jplag.cli; -import static de.jplag.cli.CommandLineArgument.BASE_CODE; -import static de.jplag.cli.CommandLineArgument.CLUSTER_AGGLOMERATIVE_INTER_CLUSTER_SIMILARITY; -import static de.jplag.cli.CommandLineArgument.CLUSTER_AGGLOMERATIVE_THRESHOLD; -import static de.jplag.cli.CommandLineArgument.CLUSTER_ALGORITHM; -import static de.jplag.cli.CommandLineArgument.CLUSTER_DISABLE; -import static de.jplag.cli.CommandLineArgument.CLUSTER_METRIC; -import static de.jplag.cli.CommandLineArgument.CLUSTER_PREPROCESSING_CDF; -import static de.jplag.cli.CommandLineArgument.CLUSTER_PREPROCESSING_NONE; -import static de.jplag.cli.CommandLineArgument.CLUSTER_PREPROCESSING_PERCENTILE; -import static de.jplag.cli.CommandLineArgument.CLUSTER_PREPROCESSING_THRESHOLD; -import static de.jplag.cli.CommandLineArgument.CLUSTER_SPECTRAL_BANDWIDTH; -import static de.jplag.cli.CommandLineArgument.CLUSTER_SPECTRAL_KMEANS_ITERATIONS; -import static de.jplag.cli.CommandLineArgument.CLUSTER_SPECTRAL_MAX_RUNS; -import static de.jplag.cli.CommandLineArgument.CLUSTER_SPECTRAL_MIN_RUNS; -import static de.jplag.cli.CommandLineArgument.CLUSTER_SPECTRAL_NOISE; -import static de.jplag.cli.CommandLineArgument.DEBUG; -import static de.jplag.cli.CommandLineArgument.EXCLUDE_FILE; -import static de.jplag.cli.CommandLineArgument.LANGUAGE; -import static de.jplag.cli.CommandLineArgument.MIN_TOKEN_MATCH; -import static de.jplag.cli.CommandLineArgument.NEW_DIRECTORY; -import static de.jplag.cli.CommandLineArgument.OLD_DIRECTORY; -import static de.jplag.cli.CommandLineArgument.RESULT_FOLDER; -import static de.jplag.cli.CommandLineArgument.ROOT_DIRECTORY; -import static de.jplag.cli.CommandLineArgument.SHOWN_COMPARISONS; -import static de.jplag.cli.CommandLineArgument.SIMILARITY_THRESHOLD; -import static de.jplag.cli.CommandLineArgument.SUBDIRECTORY; -import static de.jplag.cli.CommandLineArgument.SUFFIXES; +import static picocli.CommandLine.Model.UsageMessageSpec.SECTION_KEY_DESCRIPTION_HEADING; +import static picocli.CommandLine.Model.UsageMessageSpec.SECTION_KEY_OPTION_LIST; +import static picocli.CommandLine.Model.UsageMessageSpec.SECTION_KEY_SYNOPSIS; import java.io.File; import java.security.SecureRandom; -import java.util.ArrayList; -import java.util.Arrays; +import java.util.HashSet; import java.util.List; import java.util.Random; +import java.util.Set; import java.util.stream.Collectors; import org.slf4j.ILoggerFactory; @@ -42,17 +18,21 @@ import de.jplag.JPlag; import de.jplag.JPlagResult; +import de.jplag.Language; import de.jplag.cli.logger.CollectedLoggerFactory; import de.jplag.clustering.ClusteringOptions; import de.jplag.clustering.Preprocessing; import de.jplag.exceptions.ExitException; +import de.jplag.merging.MergingOptions; import de.jplag.options.JPlagOptions; +import de.jplag.options.LanguageOption; +import de.jplag.options.LanguageOptions; import de.jplag.reporting.reportobject.ReportObjectFactory; -import net.sourceforge.argparse4j.ArgumentParsers; -import net.sourceforge.argparse4j.inf.ArgumentParser; -import net.sourceforge.argparse4j.inf.ArgumentParserException; -import net.sourceforge.argparse4j.inf.Namespace; +import picocli.CommandLine; +import picocli.CommandLine.Model.CommandSpec; +import picocli.CommandLine.Model.OptionSpec; +import picocli.CommandLine.ParseResult; /** * Command line interface class, allows using via command line. @@ -68,13 +48,18 @@ public final class CLI { private static final String[] DESCRIPTIONS = {"Detecting Software Plagiarism", "Software-Archaeological Playground", "Since 1996", "Scientifically Published", "Maintained by SDQ", "RIP Structure and Table", "What else?", "You have been warned!", "Since Java 1.0", - "More Abstract than Tree", "Students Nightmare", "No, changing variable names does not work", "The tech is out there!"}; + "More Abstract than Tree", "Students Nightmare", "No, changing variable names does not work", "The tech is out there!", + "Developed by plagiarism experts."}; - private static final String PROGRAM_NAME = "jplag"; - static final String CLUSTERING_GROUP_NAME = "Clustering"; - static final String ADVANCED_GROUP = "Advanced"; + private static final String OPTION_LIST_HEADING = "Parameter descriptions: "; - private final ArgumentParser parser; + private final CommandLine commandLine; + private final CliOptions options; + + private static final String IMPOSSIBLE_EXCEPTION = "This should not have happened." + + " Please create an issue on github (https://github.com/jplag/JPlag/issues) with the entire output."; + + private static final String DESCRIPTION_PATTERN = "%nJPlag - %s%n%s%n%n"; /** * Main class for using JPlag via the CLI. @@ -83,14 +68,17 @@ public final class CLI { public static void main(String[] args) { try { logger.debug("Your version of JPlag is {}", JPlag.JPLAG_VERSION); + CLI cli = new CLI(); - Namespace arguments = cli.parseArguments(args); - JPlagOptions options = cli.buildOptionsFromArguments(arguments); - JPlag jplag = new JPlag(options); - logger.debug("JPlag initialized"); - JPlagResult result = jplag.run(); - ReportObjectFactory reportObjectFactory = new ReportObjectFactory(); - reportObjectFactory.createAndSaveReport(result, arguments.getString(RESULT_FOLDER.flagWithoutDash())); + + ParseResult parseResult = cli.parseOptions(args); + + if (!parseResult.isUsageHelpRequested() && !(parseResult.subcommand() != null && parseResult.subcommand().isUsageHelpRequested())) { + JPlagOptions options = cli.buildOptionsFromArguments(parseResult); + JPlagResult result = JPlag.run(options); + ReportObjectFactory reportObjectFactory = new ReportObjectFactory(); + reportObjectFactory.createAndSaveReport(result, cli.getResultFolder()); + } } catch (ExitException exception) { logger.error(exception.getMessage()); // do not pass exception here to keep log clean finalizeLogger(); @@ -98,138 +86,160 @@ public static void main(String[] args) { } } - private static void finalizeLogger() { - ILoggerFactory factory = LoggerFactory.getILoggerFactory(); - if (!(factory instanceof CollectedLoggerFactory collectedLoggerFactory)) - return; - collectedLoggerFactory.finalizeInstances(); - } - /** - * Creates the command line interface and initializes the argument parser. + * Creates a new instance */ public CLI() { - parser = ArgumentParsers.newFor(PROGRAM_NAME).build().defaultHelp(true).description(generateDescription()); - CliGroupHelper groupHelper = new CliGroupHelper(parser); - for (CommandLineArgument argument : CommandLineArgument.values()) { - argument.parseWith(parser, groupHelper); - } + this.options = new CliOptions(); + this.commandLine = new CommandLine(options); + + this.commandLine.setHelpFactory(new HelpFactory()); + + this.commandLine.getHelpSectionMap().put(SECTION_KEY_OPTION_LIST, help -> help.optionList().lines().map(it -> { + if (it.startsWith(" -")) { + return " " + it; + } else { + return it; + } + }).collect(Collectors.joining(System.lineSeparator()))); + + buildSubcommands().forEach(commandLine::addSubcommand); + + this.commandLine.getHelpSectionMap().put(SECTION_KEY_SYNOPSIS, help -> help.synopsis(help.synopsisHeadingLength()) + generateDescription()); + this.commandLine.getHelpSectionMap().put(SECTION_KEY_DESCRIPTION_HEADING, help -> OPTION_LIST_HEADING); + this.commandLine.setAllowSubcommandsAsOptionParameters(true); + } + + private List buildSubcommands() { + return LanguageLoader.getAllAvailableLanguages().values().stream().map(language -> { + CommandSpec command = CommandSpec.create().name(language.getIdentifier()); + + for (LanguageOption option : language.getOptions().getOptionsAsList()) { + command.addOption(OptionSpec.builder(option.getNameAsUnixParameter()).type(option.getType().getJavaType()) + .description(option.getDescription()).build()); + } + command.mixinStandardHelpOptions(true); + command.addPositional( + CommandLine.Model.PositionalParamSpec.builder().type(List.class).auxiliaryTypes(File.class).hidden(true).required(false).build()); + + return command; + }).toList(); } /** - * Parses an array of argument strings. - * @param arguments is the array to parse. - * @return the parsed arguments in a {@link Namespace} format. + * Parses the options from the given command line arguments. Also prints help pages when requested. + * @param args The command line arguments + * @return the parse result generated by picocli */ - public Namespace parseArguments(String[] arguments) { + public ParseResult parseOptions(String... args) throws CliException { try { - return parser.parseArgs(arguments); - } catch (ArgumentParserException exception) { - parser.handleError(exception); - System.exit(1); + ParseResult result = commandLine.parseArgs(args); + if (result.isUsageHelpRequested() || (result.subcommand() != null && result.subcommand().isUsageHelpRequested())) { + commandLine.getExecutionStrategy().execute(result); + } + return result; + } catch (CommandLine.PicocliException e) { + throw new CliException("Error during parsing", e); } - return null; + } + + private static void finalizeLogger() { + ILoggerFactory factory = LoggerFactory.getILoggerFactory(); + if (!(factory instanceof CollectedLoggerFactory collectedLoggerFactory)) { + return; + } + collectedLoggerFactory.finalizeInstances(); } /** - * Builds a options instance from parsed arguments. - * @param namespace encapsulates the parsed arguments in a {@link Namespace} format. - * @return the newly built options.F + * Builds an options instance from parsed options. + * @return the newly built options */ - public JPlagOptions buildOptionsFromArguments(Namespace namespace) { - String fileSuffixString = SUFFIXES.getFrom(namespace); - String[] fileSuffixes = new String[] {}; - if (fileSuffixString != null) { - fileSuffixes = fileSuffixString.replaceAll("\\s+", "").split(","); - } + public JPlagOptions buildOptionsFromArguments(ParseResult parseResult) throws CliException { + Set submissionDirectories = new HashSet<>(List.of(this.options.rootDirectory)); + Set oldSubmissionDirectories = Set.of(this.options.oldDirectories); + List suffixes = List.of(this.options.advanced.suffixes); + submissionDirectories.addAll(List.of(this.options.newDirectories)); - // Collect the root directories. - List submissionDirectoryPaths = new ArrayList<>(); - List oldSubmissionDirectoryPaths = new ArrayList<>(); - addAllMultiValueArgument(ROOT_DIRECTORY.getListFrom(namespace), submissionDirectoryPaths); - addAllMultiValueArgument(NEW_DIRECTORY.getListFrom(namespace), submissionDirectoryPaths); - addAllMultiValueArgument(OLD_DIRECTORY.getListFrom(namespace), oldSubmissionDirectoryPaths); - var submissionDirectories = submissionDirectoryPaths.stream().map(File::new).collect(Collectors.toSet()); - var oldSubmissionDirectories = oldSubmissionDirectoryPaths.stream().map(File::new).collect(Collectors.toSet()); + if (parseResult.subcommand() != null && parseResult.subcommand().hasMatchedPositional(0)) { + submissionDirectories.addAll(parseResult.subcommand().matchedPositional(0).getValue()); + } - var language = LanguageLoader.getLanguage(LANGUAGE.getFrom(namespace)).orElseThrow(); - ClusteringOptions clusteringOptions = getClusteringOptions(namespace); + ClusteringOptions clusteringOptions = getClusteringOptions(this.options); + MergingOptions mergingOptions = getMergingOptions(this.options); - JPlagOptions options = new JPlagOptions(language, MIN_TOKEN_MATCH.getFrom(namespace), submissionDirectories, oldSubmissionDirectories, null, - SUBDIRECTORY.getFrom(namespace), Arrays.stream(fileSuffixes).toList(), EXCLUDE_FILE.getFrom(namespace), - JPlagOptions.DEFAULT_SIMILARITY_METRIC, SIMILARITY_THRESHOLD.getFrom(namespace), SHOWN_COMPARISONS.getFrom(namespace), - clusteringOptions, DEBUG.getFrom(namespace)); + JPlagOptions jPlagOptions = new JPlagOptions(loadLanguage(parseResult), this.options.minTokenMatch, submissionDirectories, + oldSubmissionDirectories, null, this.options.advanced.subdirectory, suffixes, this.options.advanced.exclusionFileName, + JPlagOptions.DEFAULT_SIMILARITY_METRIC, this.options.advanced.similarityThreshold, this.options.shownComparisons, clusteringOptions, + this.options.advanced.debug, mergingOptions); - String baseCodePath = BASE_CODE.getFrom(namespace); + String baseCodePath = this.options.baseCode; File baseCodeDirectory = baseCodePath == null ? null : new File(baseCodePath); if (baseCodeDirectory == null || baseCodeDirectory.exists()) { - return options.withBaseCodeSubmissionDirectory(baseCodeDirectory); + return jPlagOptions.withBaseCodeSubmissionDirectory(baseCodeDirectory); } else { logger.warn("Using legacy partial base code API. Please migrate to new full path base code API."); - return options.withBaseCodeSubmissionName(baseCodePath); + return jPlagOptions.withBaseCodeSubmissionName(baseCodePath); } } - private static ClusteringOptions getClusteringOptions(Namespace namespace) { - ClusteringOptions clusteringOptions = new ClusteringOptions(); - if (CLUSTER_DISABLE.isSet(namespace)) { - boolean disabled = CLUSTER_DISABLE.getFrom(namespace); - clusteringOptions = clusteringOptions.withEnabled(!disabled); - } - if (CLUSTER_ALGORITHM.isSet(namespace)) { - clusteringOptions = clusteringOptions.withAlgorithm(CLUSTER_ALGORITHM.getFrom(namespace)); - } - if (CLUSTER_METRIC.isSet(namespace)) { - clusteringOptions = clusteringOptions.withSimilarityMetric(CLUSTER_METRIC.getFrom(namespace)); - } - if (CLUSTER_SPECTRAL_BANDWIDTH.isSet(namespace)) { - clusteringOptions = clusteringOptions.withSpectralKernelBandwidth(CLUSTER_SPECTRAL_BANDWIDTH.getFrom(namespace)); - } - if (CLUSTER_SPECTRAL_NOISE.isSet(namespace)) { - clusteringOptions = clusteringOptions.withSpectralGaussianProcessVariance(CLUSTER_SPECTRAL_NOISE.getFrom(namespace)); - } - if (CLUSTER_SPECTRAL_MIN_RUNS.isSet(namespace)) { - clusteringOptions = clusteringOptions.withSpectralMinRuns(CLUSTER_SPECTRAL_MIN_RUNS.getFrom(namespace)); - } - if (CLUSTER_SPECTRAL_MAX_RUNS.isSet(namespace)) { - clusteringOptions = clusteringOptions.withSpectralMaxRuns(CLUSTER_SPECTRAL_MAX_RUNS.getFrom(namespace)); - } - if (CLUSTER_SPECTRAL_KMEANS_ITERATIONS.isSet(namespace)) { - clusteringOptions = clusteringOptions.withSpectralMaxKMeansIterationPerRun(CLUSTER_SPECTRAL_KMEANS_ITERATIONS.getFrom(namespace)); - } - if (CLUSTER_AGGLOMERATIVE_THRESHOLD.isSet(namespace)) { - clusteringOptions = clusteringOptions.withAgglomerativeThreshold(CLUSTER_AGGLOMERATIVE_THRESHOLD.getFrom(namespace)); - } - if (CLUSTER_AGGLOMERATIVE_INTER_CLUSTER_SIMILARITY.isSet(namespace)) { - clusteringOptions = clusteringOptions - .withAgglomerativeInterClusterSimilarity(CLUSTER_AGGLOMERATIVE_INTER_CLUSTER_SIMILARITY.getFrom(namespace)); + private Language loadLanguage(ParseResult result) throws CliException { + if (result.subcommand() != null) { + ParseResult subcommandResult = result.subcommand(); + Language language = LanguageLoader.getLanguage(subcommandResult.commandSpec().name()) + .orElseThrow(() -> new CliException(IMPOSSIBLE_EXCEPTION)); + LanguageOptions languageOptions = language.getOptions(); + languageOptions.getOptionsAsList().forEach(option -> { + if (subcommandResult.hasMatchedOption(option.getNameAsUnixParameter())) { + option.setValue(subcommandResult.matchedOptionValue(option.getNameAsUnixParameter(), null)); + } + }); + return language; + } else { + return this.options.language; } - if (CLUSTER_PREPROCESSING_NONE.isSet(namespace) && Boolean.TRUE.equals(CLUSTER_PREPROCESSING_NONE.getFrom(namespace))) { + } + + private static ClusteringOptions getClusteringOptions(CliOptions options) { + ClusteringOptions clusteringOptions = new ClusteringOptions().withEnabled(!options.clustering.disable) + .withAlgorithm(options.clustering.enabled.algorithm).withSimilarityMetric(options.clustering.enabled.metric) + .withSpectralKernelBandwidth(options.clusterSpectralBandwidth).withSpectralGaussianProcessVariance(options.clusterSpectralNoise) + .withSpectralMinRuns(options.clusterSpectralMinRuns).withSpectralMaxRuns(options.clusterSpectralMaxRuns) + .withSpectralMaxKMeansIterationPerRun(options.clusterSpectralKMeansIterations) + .withAgglomerativeThreshold(options.clusterAgglomerativeThreshold) + .withAgglomerativeInterClusterSimilarity(options.clusterAgglomerativeInterClusterSimilarity); + + if (options.clusterPreprocessingNone) { clusteringOptions = clusteringOptions.withPreprocessor(Preprocessing.NONE); } - if (CLUSTER_PREPROCESSING_CDF.isSet(namespace) && Boolean.TRUE.equals(CLUSTER_PREPROCESSING_CDF.getFrom(namespace))) { + + if (options.clusterPreprocessingCdf) { clusteringOptions = clusteringOptions.withPreprocessor(Preprocessing.CUMULATIVE_DISTRIBUTION_FUNCTION); } - if (CLUSTER_PREPROCESSING_PERCENTILE.isSet(namespace)) { + + if (options.clusterPreprocessingPercentile != 0) { clusteringOptions = clusteringOptions.withPreprocessor(Preprocessing.PERCENTILE) - .withPreprocessorPercentile(CLUSTER_PREPROCESSING_PERCENTILE.getFrom(namespace)); + .withPreprocessorPercentile(options.clusterPreprocessingPercentile); } - if (CLUSTER_PREPROCESSING_THRESHOLD.isSet(namespace)) { + + if (options.clusterPreprocessingThreshold != 0) { clusteringOptions = clusteringOptions.withPreprocessor(Preprocessing.THRESHOLD) - .withPreprocessorPercentile(CLUSTER_PREPROCESSING_THRESHOLD.getFrom(namespace)); + .withPreprocessorThreshold(options.clusterPreprocessingThreshold); } + return clusteringOptions; } + private static MergingOptions getMergingOptions(CliOptions options) { + return new MergingOptions(options.merging.enabled, options.merging.minimumNeighborLength, options.merging.maximumGapSize); + } + private String generateDescription() { var randomDescription = DESCRIPTIONS[RANDOM.nextInt(DESCRIPTIONS.length)]; - return String.format("JPlag - %s%n%n%s", randomDescription, CREDITS); + return String.format(DESCRIPTION_PATTERN, randomDescription, CREDITS); } - private void addAllMultiValueArgument(List> argumentValues, List destinationRootDirectories) { - if (argumentValues == null) { - return; - } - argumentValues.forEach(destinationRootDirectories::addAll); + public String getResultFolder() { + return this.options.resultFolder; } } diff --git a/cli/src/main/java/de/jplag/cli/CliException.java b/cli/src/main/java/de/jplag/cli/CliException.java new file mode 100644 index 000000000..336319bc2 --- /dev/null +++ b/cli/src/main/java/de/jplag/cli/CliException.java @@ -0,0 +1,13 @@ +package de.jplag.cli; + +import de.jplag.exceptions.ExitException; + +public class CliException extends ExitException { + public CliException(String message) { + super(message); + } + + public CliException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/cli/src/main/java/de/jplag/cli/CliGroupHelper.java b/cli/src/main/java/de/jplag/cli/CliGroupHelper.java deleted file mode 100644 index af801e2bd..000000000 --- a/cli/src/main/java/de/jplag/cli/CliGroupHelper.java +++ /dev/null @@ -1,33 +0,0 @@ -package de.jplag.cli; - -import java.util.HashMap; -import java.util.Map; - -import net.sourceforge.argparse4j.inf.ArgumentContainer; -import net.sourceforge.argparse4j.inf.ArgumentGroup; -import net.sourceforge.argparse4j.inf.ArgumentParser; -import net.sourceforge.argparse4j.inf.MutuallyExclusiveGroup; - -/** - * Can be used to automatically create and reuse {@link ArgumentGroup}s and {@link MutuallyExclusiveGroup}s through - * their names only. This is useful when an {@link ArgumentParser} is not configured in an imperative fashion. - */ -public class CliGroupHelper { - - private final ArgumentParser parser; - private final Map mutuallyExclusiveGroups = new HashMap<>(); - private final Map argumentGroups = new HashMap<>(); - - public CliGroupHelper(ArgumentParser parser) { - this.parser = parser; - } - - public ArgumentContainer getMutuallyExclusiveGroup(String name) { - return mutuallyExclusiveGroups.computeIfAbsent(name, parser::addMutuallyExclusiveGroup); - } - - public ArgumentContainer getArgumentGroup(String name) { - return argumentGroups.computeIfAbsent(name, parser::addArgumentGroup); - } - -} diff --git a/cli/src/main/java/de/jplag/cli/CliOptions.java b/cli/src/main/java/de/jplag/cli/CliOptions.java new file mode 100644 index 000000000..c55e71f3b --- /dev/null +++ b/cli/src/main/java/de/jplag/cli/CliOptions.java @@ -0,0 +1,159 @@ +package de.jplag.cli; + +import java.io.File; + +import de.jplag.Language; +import de.jplag.clustering.ClusteringAlgorithm; +import de.jplag.clustering.ClusteringOptions; +import de.jplag.clustering.algorithm.InterClusterSimilarity; +import de.jplag.java.JavaLanguage; +import de.jplag.options.JPlagOptions; +import de.jplag.options.SimilarityMetric; + +import picocli.CommandLine; +import picocli.CommandLine.ArgGroup; +import picocli.CommandLine.Option; +import picocli.CommandLine.Parameters; + +@CommandLine.Command(name = "jplag", description = "", usageHelpAutoWidth = true, abbreviateSynopsis = true) +public class CliOptions implements Runnable { + public static final Language defaultLanguage = new JavaLanguage(); + + @Parameters(paramLabel = "root-dirs", description = "Root-directory with submissions to check for plagiarism%n", split = ",") + public File[] rootDirectory = new File[0]; + + @Option(names = {"--new", + "-new"}, split = ",", description = "Root-directory with submissions to check for plagiarism (same as the root directory)%n") + public File[] newDirectories = new File[0]; + + @Option(names = {"--old", "-old"}, split = ",", description = "Root-directory with prior submissions to compare against%n") + public File[] oldDirectories = new File[0]; + + @Option(names = {"--language", + "-l"}, arity = "1", converter = LanguageConverter.class, completionCandidates = LanguageCandidates.class, description = "Select the language to parse the submissions (default: java). The language names are the same as the subcommands.%n") + public Language language = defaultLanguage; + + @Option(names = {"-bc", "--bc", + "--base-code"}, description = "Path of the directory containing the base code (common framework used in all submissions)%n") + public String baseCode; + + @Option(names = {"-t", "--min-tokens"}, description = "Tunes the comparison sensitivity by adjusting the minimum token required to be counted " + + "as a matching section. A smaller increases the sensitivity but might lead to more " + "false-positives%n") + public Integer minTokenMatch = null; + + @Option(names = {"-h", "--help"}, usageHelp = true, description = "display this help and exit") + public boolean help; + + @Option(names = {"-n", + "--shown-comparisons"}, description = "The maximum number of comparisons that will be shown in the generated report, if set " + + "to -1 all comparisons will be shown (default: 100)%n") + public int shownComparisons = JPlagOptions.DEFAULT_SHOWN_COMPARISONS; + + @Option(names = {"-r", + "--result-directory"}, description = "Name of the directory in which the comparison results will be stored (default: result)%n") + public String resultFolder = "results"; + + @ArgGroup(heading = "Advanced%n", exclusive = false) + public Advanced advanced = new Advanced(); + + @ArgGroup(validate = false, heading = "Clustering%n") + public Clustering clustering = new Clustering(); + + @ArgGroup(validate = false, heading = "Merging of neighboring matches to increase the similarity of concealed plagiarism:%n") + public Merging merging = new Merging(); + + /** + * Empty run method, so picocli prints help automatically + */ + @Override + public void run() { + // Empty run method, so picocli prints help automatically + } + + public static class Advanced { + @Option(names = {"-d", "--debug"}, description = "Debug parser. Non-parsable files will be stored (default: false)%n") + public boolean debug; + + @Option(names = {"-s", "--subdirectory"}, description = "Look in directories /*/ for programs%n") + public String subdirectory; + + @Option(names = {"-p", "--suffixes"}, split = ",", description = "comma-separated list of all filename suffixes that are included%n") + public String[] suffixes = new String[0]; + + @Option(names = {"-x", + "--exclusion-file"}, description = "All files named in this file will be ignored in the comparison (line-separated list)%n") + public String exclusionFileName; + + @Option(names = {"-m", + "--similarity-threshold"}, description = "Comparison similarity threshold [0.0-1.0]: All comparisons above this threshold will " + + "be saved (default: 0.0)%n") + public double similarityThreshold = JPlagOptions.DEFAULT_SIMILARITY_THRESHOLD; + } + + public static class Clustering { + @Option(names = {"--cluster-skip"}, description = "Skips the clustering (default: false)%n") + public boolean disable; + + @ArgGroup + public ClusteringEnabled enabled = new ClusteringEnabled(); + + public static class ClusteringEnabled { + @Option(names = {"--cluster-alg", + "--cluster-algorithm"}, description = "Which clustering algorithm to use. Agglomerative merges similar submissions bottom up. " + + "Spectral clustering is combined with Bayesian Optimization to execute the k-Means " + + "clustering algorithm multiple times, hopefully finding a \"good\" clustering " + + "automatically. (default: spectral)%n") + public ClusteringAlgorithm algorithm = new ClusteringOptions().algorithm(); + + @Option(names = { + "--cluster-metric"}, description = "The metric used for clustering. AVG is intersection over union, MAX can expose some " + + "attempts of obfuscation. (default: MAX)%n") + public SimilarityMetric metric = new ClusteringOptions().similarityMetric(); + } + } + + public static class Merging { + @Option(names = {"--match-merging"}, description = "Enables match merging (default: false)%n") + public boolean enabled; + + @Option(names = {"--neighbor-length"}, description = "Defines how short a match can be, to be considered (default: 2)%n") + public int minimumNeighborLength; + + @Option(names = {"--gap-size"}, description = "Defines how many token there can be between two neighboring matches (default: 6)%n") + public int maximumGapSize; + + } + + @Option(names = {"--cluster-spectral-bandwidth"}, hidden = true) + public double clusterSpectralBandwidth = new ClusteringOptions().spectralKernelBandwidth(); + + @Option(names = {"--cluster-spectral-noise"}, hidden = true) + public double clusterSpectralNoise = new ClusteringOptions().spectralGaussianProcessVariance(); + + @Option(names = {"--cluster-spectral-min-runs"}, hidden = true) + public int clusterSpectralMinRuns = new ClusteringOptions().spectralMinRuns(); + + @Option(names = {"--cluster-spectral-max-runs"}, hidden = true) + public int clusterSpectralMaxRuns = new ClusteringOptions().spectralMaxRuns(); + + @Option(names = {"--cluster-spectral-kmeans-iterations", "--cluster-spectral-kmeans-interations"}, hidden = true) + public int clusterSpectralKMeansIterations = new ClusteringOptions().spectralMaxKMeansIterationPerRun(); + + @Option(names = {"--cluster-agglomerative-threshold"}, hidden = true) + public double clusterAgglomerativeThreshold = new ClusteringOptions().agglomerativeThreshold(); + + @Option(names = {"--cluster-agglomerative-inter-cluster-similarity"}, hidden = true) + public InterClusterSimilarity clusterAgglomerativeInterClusterSimilarity = new ClusteringOptions().agglomerativeInterClusterSimilarity(); + + @Option(names = {"--cluster-pp-none"}, hidden = true) + public boolean clusterPreprocessingNone; + + @Option(names = {"--cluster-pp-cdf"}, hidden = true) + public boolean clusterPreprocessingCdf; + + @Option(names = {"--cluster-pp-percentile"}, hidden = true) + public double clusterPreprocessingPercentile; + + @Option(names = {"--cluster-pp-threshold"}, hidden = true) + public double clusterPreprocessingThreshold; +} diff --git a/cli/src/main/java/de/jplag/cli/CommandLineArgument.java b/cli/src/main/java/de/jplag/cli/CommandLineArgument.java deleted file mode 100644 index 0b367114f..000000000 --- a/cli/src/main/java/de/jplag/cli/CommandLineArgument.java +++ /dev/null @@ -1,268 +0,0 @@ -package de.jplag.cli; - -import static de.jplag.cli.CLI.ADVANCED_GROUP; -import static de.jplag.cli.CLI.CLUSTERING_GROUP_NAME; -import static de.jplag.options.JPlagOptions.DEFAULT_SHOWN_COMPARISONS; -import static de.jplag.options.JPlagOptions.DEFAULT_SIMILARITY_THRESHOLD; -import static net.sourceforge.argparse4j.impl.Arguments.append; -import static net.sourceforge.argparse4j.impl.Arguments.storeTrue; - -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Optional; - -import de.jplag.Language; -import de.jplag.Messages; -import de.jplag.NumberOfArgumentValues; -import de.jplag.clustering.ClusteringAlgorithm; -import de.jplag.clustering.ClusteringOptions; -import de.jplag.clustering.algorithm.InterClusterSimilarity; -import de.jplag.options.SimilarityMetric; - -import net.sourceforge.argparse4j.impl.Arguments; -import net.sourceforge.argparse4j.inf.Argument; -import net.sourceforge.argparse4j.inf.ArgumentAction; -import net.sourceforge.argparse4j.inf.ArgumentContainer; -import net.sourceforge.argparse4j.inf.ArgumentParser; -import net.sourceforge.argparse4j.inf.FeatureControl; -import net.sourceforge.argparse4j.inf.Namespace; - -/** - * Command line arguments for the JPlag CLI. Each argument is defined through an enumeral. - * @author Timur Saglam - */ -public enum CommandLineArgument { - ROOT_DIRECTORY(new Builder("rootDir", String.class).nargs(NumberOfArgumentValues.ZERO_OR_MORE_VALUES)), - NEW_DIRECTORY(new Builder("-new", String.class).nargs(NumberOfArgumentValues.ONE_OR_MORE_VALUES)), - OLD_DIRECTORY(new Builder("-old", String.class).nargs(NumberOfArgumentValues.ONE_OR_MORE_VALUES)), - LANGUAGE( - new Builder("-l", String.class).defaultsTo(new de.jplag.java.Language().getIdentifier()) - .choices(LanguageLoader.getAllAvailableLanguageIdentifiers())), - BASE_CODE("-bc", String.class), - - // real logging library - DEBUG(new Builder("-d", Boolean.class).argumentGroup(ADVANCED_GROUP)), - SUBDIRECTORY(new Builder("-s", String.class).argumentGroup(ADVANCED_GROUP)), - SUFFIXES(new Builder("-p", String.class).argumentGroup(ADVANCED_GROUP)), - EXCLUDE_FILE(new Builder("-x", String.class).argumentGroup(ADVANCED_GROUP)), - MIN_TOKEN_MATCH("-t", Integer.class), - SIMILARITY_THRESHOLD(new Builder("-m", Double.class).defaultsTo(DEFAULT_SIMILARITY_THRESHOLD).argumentGroup(ADVANCED_GROUP)), - SHOWN_COMPARISONS(new Builder("-n", Integer.class).defaultsTo(DEFAULT_SHOWN_COMPARISONS)), - RESULT_FOLDER(new Builder("-r", String.class).defaultsTo("result")), - CLUSTER_DISABLE(new Builder("--cluster-skip", Boolean.class).argumentGroup(CLUSTERING_GROUP_NAME).action(Arguments.storeTrue())), - CLUSTER_ALGORITHM( - new Builder("--cluster-alg", ClusteringAlgorithm.class).argumentGroup(CLUSTERING_GROUP_NAME) - .defaultsTo(new ClusteringOptions().algorithm())), - CLUSTER_METRIC( - new Builder("--cluster-metric", SimilarityMetric.class).argumentGroup(CLUSTERING_GROUP_NAME) - .defaultsTo(new ClusteringOptions().similarityMetric())), - CLUSTER_SPECTRAL_BANDWIDTH( - new Builder("--cluster-spectral-bandwidth", Double.class).metaVar("bandwidth") - .defaultsTo(new ClusteringOptions().spectralKernelBandwidth()).hidden()), - CLUSTER_SPECTRAL_NOISE( - new Builder("--cluster-spectral-noise", Double.class).metaVar("noise") - .defaultsTo(new ClusteringOptions().spectralGaussianProcessVariance()).hidden()), - CLUSTER_SPECTRAL_MIN_RUNS( - new Builder("--cluster-spectral-min-runs", Integer.class).metaVar("min").defaultsTo(new ClusteringOptions().spectralMinRuns()).hidden()), - CLUSTER_SPECTRAL_MAX_RUNS( - new Builder("--cluster-spectral-max-runs", Integer.class).metaVar("max").defaultsTo(new ClusteringOptions().spectralMaxRuns()).hidden()), - CLUSTER_SPECTRAL_KMEANS_ITERATIONS( - new Builder("--cluster-spectral-kmeans-interations", Integer.class).metaVar("iterations") - .defaultsTo(new ClusteringOptions().spectralMaxKMeansIterationPerRun()).hidden()), - CLUSTER_AGGLOMERATIVE_THRESHOLD( - new Builder("--cluster-agglomerative-threshold", Double.class).metaVar("threshold") - .defaultsTo(new ClusteringOptions().agglomerativeThreshold()).hidden()), - CLUSTER_AGGLOMERATIVE_INTER_CLUSTER_SIMILARITY( - new Builder("--cluster-agglomerative-inter-cluster-similarity", InterClusterSimilarity.class) - .defaultsTo(new ClusteringOptions().agglomerativeInterClusterSimilarity()).hidden()), - CLUSTER_PREPROCESSING_NONE(new Builder("--cluster-pp-none", Boolean.class).action(Arguments.storeTrue()).hidden()), - CLUSTER_PREPROCESSING_CDF(new Builder("--cluster-pp-cdf", Boolean.class).action(Arguments.storeTrue()).hidden()), - CLUSTER_PREPROCESSING_PERCENTILE(new Builder("--cluster-pp-percentile", Double.class).metaVar("percentile").hidden()), - CLUSTER_PREPROCESSING_THRESHOLD(new Builder("--cluster-pp-threshold", Double.class).metaVar("threshold").hidden()); - - /** - * The identifier of the default {@link Language}. - * @see Language#getIdentifier() - */ - public static final String DEFAULT_LANGUAGE_IDENTIFIER = new de.jplag.java.Language().getIdentifier(); - - private final String flag; - private final NumberOfArgumentValues numberOfValues; - private final String description; - private final Optional defaultValue; - private final Optional> choices; - private final Optional argumentGroup; - private final Optional mutuallyExclusiveGroup; - private final Optional action; - private final Optional metaVar; - private final Class type; - private final boolean hidden; - - CommandLineArgument(String flag, Class type) { - this(new Builder(flag, type)); - } - - CommandLineArgument(Builder builder) { - this.flag = builder.flag; - this.type = builder.type; - this.defaultValue = builder.defaultValue; - this.choices = builder.choices; - this.argumentGroup = builder.argumentGroup; - this.mutuallyExclusiveGroup = builder.mutuallyExclusiveGroup; - this.action = builder.action; - this.metaVar = builder.metaVar; - this.numberOfValues = builder.nargs.orElse(NumberOfArgumentValues.SINGLE_VALUE); - this.hidden = builder.hidden; - this.description = retrieveDescriptionFromMessages(); - - } - - /** - * @return the flag name of the command line argument. - */ - public String flag() { - return flag; - } - - /** - * @return the flag name of the command line argument without leading dashes and inner dashes replaced with underscores. - */ - public String flagWithoutDash() { - return flag.replaceAll("^-+", "").replace("-", "_"); - } - - /** - * Returns the value of this argument for arguments with a single value. Convenience method for - * {@link Namespace#get(String)} and {@link CommandLineArgument#flagWithoutDash()}. - * @param is the argument type. - * @param namespace stores a value for the argument. - * @return the argument value. - */ - public T getFrom(Namespace namespace) { - return namespace.get(flagWithoutDash()); - } - - /** - * Returns whether the value of this argument is set to a value not equal to {@code null}. - * @param namespace stores a value for the argument - * @return the indicator - */ - public boolean isSet(Namespace namespace) { - return namespace.get(flagWithoutDash()) != null; - } - - /** - * Returns the value of this argument for arguments that allow more than a single value. Convenience method for - * {@link Namespace#getList(String)} and {@link CommandLineArgument#flagWithoutDash()}. - *

- * Depending on the action of the option, result types may change. - *

- * @param is the argument type. - * @param namespace stores a value for the argument. - * @return the argument value. - */ - public List getListFrom(Namespace namespace) { - return namespace.getList(flagWithoutDash()); - } - - /** - * Parses the command line argument with a specific parser. - * @param parser is that parser. - */ - public void parseWith(ArgumentParser parser, CliGroupHelper groupHelper) { - ArgumentContainer argContainer = mutuallyExclusiveGroup.map(groupHelper::getMutuallyExclusiveGroup) - .or(() -> argumentGroup.map(groupHelper::getArgumentGroup)).orElse(parser); - - Argument argument = argContainer.addArgument(flag).help(description); - choices.ifPresent(argument::choices); - defaultValue.ifPresent(argument::setDefault); - action.ifPresent(argument::action); - metaVar.ifPresent(argument::metavar); - argument.type(type); - if (type == Boolean.class) { - argument.action(storeTrue()); - } - if (hidden) { - argument.help(FeatureControl.SUPPRESS); - } - if (!numberOfValues.toString().isEmpty()) { - // For multi-value arguments keep all invocations. - // This causes the argument value to change its type to 'List>'. - // Also, when the retrieved value after parsing the CLI is 'null', the argument is not used. - argument.nargs(numberOfValues.toString()); - argument.action(append()); - } - } - - /** - * Dynamically loads the description from the message file. For an option named NEW_OPTION the messages key - * should be CommandLineArgument.NewOption. - */ - private String retrieveDescriptionFromMessages() { - StringBuilder builder = new StringBuilder(); - for (String substring : toString().toLowerCase().split("_")) { - builder.append(substring.substring(0, 1).toUpperCase()); - builder.append(substring.substring(1)); - } - return Messages.getString(getClass().getSimpleName() + "." + builder.toString()); - } - - private static class Builder { - private final String flag; - private final Class type; - private Optional defaultValue = Optional.empty(); - private Optional> choices = Optional.empty(); - private Optional argumentGroup = Optional.empty(); - private Optional mutuallyExclusiveGroup = Optional.empty(); - private Optional action = Optional.empty(); - private Optional metaVar = Optional.empty(); - private Optional nargs = Optional.empty(); - private boolean hidden; - - public Builder(String flag, Class type) { - this.flag = flag; - this.type = type; - } - - public Builder defaultsTo(Object defaultValue) { - this.defaultValue = Optional.of(defaultValue); - return this; - } - - public Builder choices(String... choices) { - this.choices = Optional.of(Arrays.asList(choices)); - return this; - } - - public Builder choices(Collection choices) { - this.choices = Optional.of(choices); - return this; - } - - public Builder argumentGroup(String argumentGroup) { - this.argumentGroup = Optional.of(argumentGroup); - return this; - } - - public Builder action(ArgumentAction action) { - this.action = Optional.of(action); - return this; - } - - public Builder metaVar(String metaVar) { - this.metaVar = Optional.of(metaVar); - return this; - } - - public Builder nargs(NumberOfArgumentValues nargs) { - this.nargs = Optional.of(nargs); - return this; - } - - public Builder hidden() { - this.hidden = true; - return this; - } - } -} diff --git a/cli/src/main/java/de/jplag/cli/CustomHelp.java b/cli/src/main/java/de/jplag/cli/CustomHelp.java new file mode 100644 index 000000000..368f358ce --- /dev/null +++ b/cli/src/main/java/de/jplag/cli/CustomHelp.java @@ -0,0 +1,26 @@ +package de.jplag.cli; + +import picocli.CommandLine; + +/** + * Custom implementation for the help page, including the custom {@link ParamLabelRenderer} + */ +public class CustomHelp extends CommandLine.Help { + private final IParamLabelRenderer paramLabelRenderer; + + /** + * New instance + * @param command The {@link picocli.CommandLine.Model.CommandSpec} to build the help for + * @param colorScheme The {@link picocli.CommandLine.Help.ColorScheme} for the help page + */ + public CustomHelp(CommandLine.Model.CommandSpec command, ColorScheme colorScheme) { + super(command, colorScheme); + + this.paramLabelRenderer = new ParamLabelRenderer(super.parameterLabelRenderer()); + } + + @Override + public IParamLabelRenderer parameterLabelRenderer() { + return this.paramLabelRenderer; + } +} diff --git a/cli/src/main/java/de/jplag/cli/HelpFactory.java b/cli/src/main/java/de/jplag/cli/HelpFactory.java new file mode 100644 index 000000000..53aa208b7 --- /dev/null +++ b/cli/src/main/java/de/jplag/cli/HelpFactory.java @@ -0,0 +1,13 @@ +package de.jplag.cli; + +import picocli.CommandLine; + +/** + * Custom help factory, used to add the custom {@link ParamLabelRenderer}. + */ +public class HelpFactory implements CommandLine.IHelpFactory { + @Override + public CommandLine.Help create(CommandLine.Model.CommandSpec commandSpec, CommandLine.Help.ColorScheme colorScheme) { + return new CustomHelp(commandSpec, colorScheme); + } +} diff --git a/cli/src/main/java/de/jplag/cli/LanguageCandidates.java b/cli/src/main/java/de/jplag/cli/LanguageCandidates.java new file mode 100644 index 000000000..715d504ea --- /dev/null +++ b/cli/src/main/java/de/jplag/cli/LanguageCandidates.java @@ -0,0 +1,15 @@ +package de.jplag.cli; + +import java.util.ArrayList; + +/** + * Helper class for picocli to find all available languages. + */ +public class LanguageCandidates extends ArrayList { + /** + * Creates a new instance. Should only be called automatically by picocli and never manually. + */ + public LanguageCandidates() { + super(LanguageLoader.getAllAvailableLanguageIdentifiers()); + } +} diff --git a/cli/src/main/java/de/jplag/cli/LanguageConverter.java b/cli/src/main/java/de/jplag/cli/LanguageConverter.java new file mode 100644 index 000000000..0a2523b95 --- /dev/null +++ b/cli/src/main/java/de/jplag/cli/LanguageConverter.java @@ -0,0 +1,15 @@ +package de.jplag.cli; + +import de.jplag.Language; + +import picocli.CommandLine; + +/** + * Helper class for picocli to convert inputs to languages. + */ +public class LanguageConverter implements CommandLine.ITypeConverter { + @Override + public Language convert(String value) { + return LanguageLoader.getLanguage(value).orElseThrow(); + } +} diff --git a/cli/src/main/java/de/jplag/cli/ParamLabelRenderer.java b/cli/src/main/java/de/jplag/cli/ParamLabelRenderer.java new file mode 100644 index 000000000..2d815af30 --- /dev/null +++ b/cli/src/main/java/de/jplag/cli/ParamLabelRenderer.java @@ -0,0 +1,44 @@ +package de.jplag.cli; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import picocli.CommandLine; + +/** + * Custom implementation of {@link picocli.CommandLine.Help.IParamLabelRenderer}, that show the available options for + * enums. For all other parameter types, the base renderer is called. + */ +public class ParamLabelRenderer implements CommandLine.Help.IParamLabelRenderer { + private final CommandLine.Help.IParamLabelRenderer base; + + private static final String PARAM_LABEL_PATTERN = "=<{%s}>"; + private static final String VALUE_SEPARATOR = ", "; + + /** + * New instance + * @param base The base renderer used for all non enum types + */ + public ParamLabelRenderer(CommandLine.Help.IParamLabelRenderer base) { + this.base = base; + } + + @Override + public CommandLine.Help.Ansi.Text renderParameterLabel(CommandLine.Model.ArgSpec argSpec, CommandLine.Help.Ansi ansi, + List styles) { + if (argSpec.type().isEnum()) { + @SuppressWarnings("unchecked") + Enum[] enumConstants = ((Class>) argSpec.type()).getEnumConstants(); + String enumValueNames = Arrays.stream(enumConstants).map(Enum::name).collect(Collectors.joining(VALUE_SEPARATOR)); + return CommandLine.Help.Ansi.AUTO.text(String.format(PARAM_LABEL_PATTERN, enumValueNames)); + } + + return base.renderParameterLabel(argSpec, ansi, styles); + } + + @Override + public String separator() { + return base.separator(); + } +} diff --git a/cli/src/main/java/de/jplag/cli/logger/CollectedLogger.java b/cli/src/main/java/de/jplag/cli/logger/CollectedLogger.java index 9d21bbcbd..80d94a74a 100644 --- a/cli/src/main/java/de/jplag/cli/logger/CollectedLogger.java +++ b/cli/src/main/java/de/jplag/cli/logger/CollectedLogger.java @@ -73,8 +73,6 @@ private void log(int level, String message, Throwable throwable, Date timeOfErro // Append date-time builder.append(dateFormat.format(timeOfError == null ? new Date() : timeOfError)).append(' '); - // Append current thread name - builder.append('[').append(Thread.currentThread().getName()).append("] "); // Append current Level builder.append('[').append(renderLevel(level)).append(']').append(' '); @@ -140,6 +138,7 @@ private String renderLevel(int level) { }; } + @Override public boolean isTraceEnabled() { return isLevelEnabled(LOG_LEVEL_TRACE); } @@ -149,114 +148,142 @@ public void trace(String message) { log(LOG_LEVEL_TRACE, message, null); } + @Override public void trace(String format, Object param1) { formatAndLog(LOG_LEVEL_TRACE, format, param1, null); } + @Override public void trace(String format, Object param1, Object param2) { formatAndLog(LOG_LEVEL_TRACE, format, param1, param2); } + @Override public void trace(String format, Object... argArray) { formatAndLog(LOG_LEVEL_TRACE, format, argArray); } + @Override public void trace(String message, Throwable t) { log(LOG_LEVEL_TRACE, message, t); } + @Override public boolean isDebugEnabled() { return isLevelEnabled(LOG_LEVEL_DEBUG); } + @Override public void debug(String message) { log(LOG_LEVEL_DEBUG, message, null); } + @Override public void debug(String format, Object param1) { formatAndLog(LOG_LEVEL_DEBUG, format, param1, null); } + @Override public void debug(String format, Object param1, Object param2) { formatAndLog(LOG_LEVEL_DEBUG, format, param1, param2); } + @Override public void debug(String format, Object... argArray) { formatAndLog(LOG_LEVEL_DEBUG, format, argArray); } + @Override public void debug(String message, Throwable throwable) { log(LOG_LEVEL_DEBUG, message, throwable); } + @Override public boolean isInfoEnabled() { return isLevelEnabled(LOG_LEVEL_INFO); } + @Override public void info(String message) { log(LOG_LEVEL_INFO, message, null); } + @Override public void info(String format, Object arg) { formatAndLog(LOG_LEVEL_INFO, format, arg, null); } + @Override public void info(String format, Object arg1, Object arg2) { formatAndLog(LOG_LEVEL_INFO, format, arg1, arg2); } + @Override public void info(String format, Object... argArray) { formatAndLog(LOG_LEVEL_INFO, format, argArray); } + @Override public void info(String message, Throwable throwable) { log(LOG_LEVEL_INFO, message, throwable); } + @Override public boolean isWarnEnabled() { return isLevelEnabled(LOG_LEVEL_WARN); } + @Override public void warn(String message) { log(LOG_LEVEL_WARN, message, null); } + @Override public void warn(String format, Object arg) { formatAndLog(LOG_LEVEL_WARN, format, arg, null); } + @Override public void warn(String format, Object arg1, Object arg2) { formatAndLog(LOG_LEVEL_WARN, format, arg1, arg2); } + @Override public void warn(String format, Object... argArray) { formatAndLog(LOG_LEVEL_WARN, format, argArray); } + @Override public void warn(String message, Throwable throwable) { log(LOG_LEVEL_WARN, message, throwable); } + @Override public boolean isErrorEnabled() { return isLevelEnabled(LOG_LEVEL_ERROR); } + @Override public void error(String message) { log(LOG_LEVEL_ERROR, message, null); } + @Override public void error(String format, Object arg) { formatAndLog(LOG_LEVEL_ERROR, format, arg, null); } + @Override public void error(String format, Object arg1, Object arg2) { formatAndLog(LOG_LEVEL_ERROR, format, arg1, arg2); } + @Override public void error(String format, Object... argArray) { formatAndLog(LOG_LEVEL_ERROR, format, argArray); } + @Override public void error(String message, Throwable throwable) { log(LOG_LEVEL_ERROR, message, throwable); } diff --git a/cli/src/main/java/de/jplag/cli/logger/CollectedLoggerFactory.java b/cli/src/main/java/de/jplag/cli/logger/CollectedLoggerFactory.java index 1971e4da9..ffba004b9 100644 --- a/cli/src/main/java/de/jplag/cli/logger/CollectedLoggerFactory.java +++ b/cli/src/main/java/de/jplag/cli/logger/CollectedLoggerFactory.java @@ -23,6 +23,7 @@ public CollectedLoggerFactory() { /** * Return an appropriate {@link CollectedLogger} instance by name. */ + @Override public Logger getLogger(String name) { CollectedLogger simpleLogger = loggerMap.get(name); if (simpleLogger != null) { diff --git a/cli/src/test/java/de/jplag/cli/AdvancedGroupTest.java b/cli/src/test/java/de/jplag/cli/AdvancedGroupTest.java new file mode 100644 index 000000000..bc88af731 --- /dev/null +++ b/cli/src/test/java/de/jplag/cli/AdvancedGroupTest.java @@ -0,0 +1,23 @@ +package de.jplag.cli; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Arrays; + +import org.junit.jupiter.api.Test; + +class AdvancedGroupTest extends CommandLineInterfaceTest { + private static final String SUFFIXES = ".sc,.scala"; + + private static final double SIMILARITY_THRESHOLD = 0.5; + + /** + * Verify that it is possible to set multiple options in the "advanced" options group. + */ + @Test + void testNotExclusive() throws CliException { + buildOptionsFromCLI(defaultArguments().suffixes(SUFFIXES).similarityThreshold(SIMILARITY_THRESHOLD)); + assertEquals(Arrays.stream(SUFFIXES.split(",")).toList(), options.fileSuffixes()); + assertEquals(0.5, options.similarityThreshold()); + } +} diff --git a/cli/src/test/java/de/jplag/cli/ArgumentBuilder.java b/cli/src/test/java/de/jplag/cli/ArgumentBuilder.java new file mode 100644 index 000000000..b5503791b --- /dev/null +++ b/cli/src/test/java/de/jplag/cli/ArgumentBuilder.java @@ -0,0 +1,186 @@ +package de.jplag.cli; + +import java.util.ArrayList; +import java.util.List; + +/** + * Builds the argument string for tests + */ +public class ArgumentBuilder { + private final List arguments; + + /** + * New instance, prefer using {@link CommandLineInterfaceTest#arguments()} or + * {@link CommandLineInterfaceTest#defaultArguments()} + */ + public ArgumentBuilder() { + this.arguments = new ArrayList<>(); + } + + /** + * Sets the root directory option + * @param directoryNames The names of the root directories + * @return self reference + */ + public ArgumentBuilder rootDirectory(String... directoryNames) { + this.arguments.add(String.join(",", directoryNames)); + return this; + } + + /** + * Sets the new root directory option + * @param directoryNames The directory names + * @return self reference + */ + public ArgumentBuilder newRootDirectories(String... directoryNames) { + this.arguments.add("--new=" + String.join(",", directoryNames)); + return this; + } + + /** + * Sets the old directory option + * @param directoryNames The directory names + * @return self reference + */ + public ArgumentBuilder oldRootDirectories(String... directoryNames) { + this.arguments.add("--old"); + this.arguments.add(String.join(",", directoryNames)); + return this; + } + + /** + * Sets the base code option + * @param baseCode The base code directory + * @return self reference + */ + public ArgumentBuilder baseCode(String baseCode) { + this.arguments.add("--base-code=" + baseCode); + return this; + } + + /** + * Sets the skip clustering option + * @return self reference + */ + public ArgumentBuilder skipClustering() { + this.arguments.add("--cluster-skip"); + return this; + } + + /** + * Sets the clustering preprocessor percentile option + * @param percentile The option value + * @return self reference + */ + public ArgumentBuilder clusterPpPercentile(double percentile) { + this.arguments.add("--cluster-pp-percentile=" + percentile); + return this; + } + + /** + * Sets the clustering preprocessor to cdf + * @return self reference + */ + public ArgumentBuilder clusterPpCdf() { + this.arguments.add("--cluster-pp-cdf"); + return this; + } + + /** + * Sets the clustering preprocessor to none + * @return self reference + */ + public ArgumentBuilder clusterPpNone() { + this.arguments.add("--cluster-pp-none"); + return this; + } + + /** + * Sets the language as an option + * @param languageName The identifier of the language + * @return self reference + */ + public ArgumentBuilder language(String languageName) { + this.arguments.add("-l"); + this.arguments.add(languageName); + return this; + } + + /** + * Sets the suffixes option + * @param suffixes The suffixes + * @return self reference + */ + public ArgumentBuilder suffixes(String... suffixes) { + this.arguments.add("-p"); + this.arguments.add(String.join(",", suffixes)); + return this; + } + + /** + * Sets the min tokens option as a string, so invalid values can be configured + * @param value The option value + * @return self reference + */ + public ArgumentBuilder minTokens(String value) { + this.arguments.add("--min-tokens"); + this.arguments.add(value); + return this; + } + + /** + * Sets the min tokens option + * @param count The min token count + * @return self reference + */ + public ArgumentBuilder minTokens(int count) { + return minTokens(String.valueOf(count)); + } + + /** + * Sets the similarity threshold as a string, so invalid values can be configures + * @param value The value + * @return self reference + */ + public ArgumentBuilder similarityThreshold(String value) { + this.arguments.add("-m"); + this.arguments.add(value); + return this; + } + + /** + * Sets the similarity threshold + * @param value The threshold + * @return self reference + */ + public ArgumentBuilder similarityThreshold(double value) { + return similarityThreshold(String.valueOf(value)); + } + + /** + * Sets the shown comparisons option as a string, so invalid values can be configured + * @param value The value + * @return self reference + */ + public ArgumentBuilder shownComparisons(String value) { + this.arguments.add("-n"); + this.arguments.add(value); + return this; + } + + /** + * Sets the shown comparisons option + * @param value The option value + * @return self reference + */ + public ArgumentBuilder shownComparisons(int value) { + return shownComparisons(String.valueOf(value)); + } + + /** + * @return The list of arguments as a string array + */ + public String[] getArgumentsAsArray() { + return this.arguments.toArray(new String[0]); + } +} diff --git a/cli/src/test/java/de/jplag/cli/BaseCodeOptionTest.java b/cli/src/test/java/de/jplag/cli/BaseCodeOptionTest.java index 996add653..6967056e5 100644 --- a/cli/src/test/java/de/jplag/cli/BaseCodeOptionTest.java +++ b/cli/src/test/java/de/jplag/cli/BaseCodeOptionTest.java @@ -10,15 +10,14 @@ class BaseCodeOptionTest extends CommandLineInterfaceTest { private static final String NAME = "BaseCodeName"; @Test - void testDefaultValue() { - buildOptionsFromCLI(CURRENT_DIRECTORY); + void testDefaultValue() throws CliException { + buildOptionsFromCLI(defaultArguments()); assertNull(options.baseCodeSubmissionDirectory()); } @Test - void testCustomName() { - String argument = buildArgument(CommandLineArgument.BASE_CODE, NAME); - buildOptionsFromCLI(argument, CURRENT_DIRECTORY); + void testCustomName() throws CliException { + buildOptionsFromCLI(defaultArguments().baseCode(NAME)); assertEquals(NAME, options.baseCodeSubmissionDirectory().getName()); } } diff --git a/cli/src/test/java/de/jplag/cli/ClusteringTest.java b/cli/src/test/java/de/jplag/cli/ClusteringTest.java index 11cff50a8..bf591726e 100644 --- a/cli/src/test/java/de/jplag/cli/ClusteringTest.java +++ b/cli/src/test/java/de/jplag/cli/ClusteringTest.java @@ -1,6 +1,6 @@ package de.jplag.cli; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.Test; @@ -8,40 +8,34 @@ class ClusteringTest extends CommandLineInterfaceTest { - private static final double EPSILON = 0.000001; - @Test - void parseSkipClustering() { - String argument = CommandLineArgument.CLUSTER_DISABLE.flag(); - buildOptionsFromCLI(argument, CURRENT_DIRECTORY); - assertEquals(false, options.clusteringOptions().enabled()); + void parseSkipClustering() throws CliException { + buildOptionsFromCLI(defaultArguments().skipClustering()); + assertFalse(options.clusteringOptions().enabled()); } @Test - void parseDefaultClustering() { - buildOptionsFromCLI(CURRENT_DIRECTORY); - assertEquals(true, options.clusteringOptions().enabled()); + void parseDefaultClustering() throws CliException { + buildOptionsFromCLI(defaultArguments()); + assertTrue(options.clusteringOptions().enabled()); } @Test - void parsePercentilePreProcessor() { - String argument = buildArgument(CommandLineArgument.CLUSTER_PREPROCESSING_PERCENTILE, Double.toString(0.5)); - buildOptionsFromCLI(argument, CURRENT_DIRECTORY); + void parsePercentilePreProcessor() throws CliException { + buildOptionsFromCLI(defaultArguments().clusterPpPercentile(.5)); assertEquals(Preprocessing.PERCENTILE, options.clusteringOptions().preprocessor()); - assertEquals(0.5, options.clusteringOptions().preprocessorPercentile(), EPSILON); + assertEquals(0.5, options.clusteringOptions().preprocessorPercentile()); } @Test - void parseCdfPreProcessor() { - String argument = CommandLineArgument.CLUSTER_PREPROCESSING_CDF.flag(); - buildOptionsFromCLI(argument, CURRENT_DIRECTORY); + void parseCdfPreProcessor() throws CliException { + buildOptionsFromCLI(defaultArguments().clusterPpCdf()); assertEquals(Preprocessing.CUMULATIVE_DISTRIBUTION_FUNCTION, options.clusteringOptions().preprocessor()); } @Test - void parseNoPreProcessor() { - String argument = CommandLineArgument.CLUSTER_PREPROCESSING_NONE.flag(); - buildOptionsFromCLI(argument, CURRENT_DIRECTORY); + void parseNoPreProcessor() throws CliException { + buildOptionsFromCLI(defaultArguments().clusterPpNone()); assertEquals(Preprocessing.NONE, options.clusteringOptions().preprocessor()); } diff --git a/cli/src/test/java/de/jplag/cli/CommandLineInterfaceTest.java b/cli/src/test/java/de/jplag/cli/CommandLineInterfaceTest.java index 4eb44e508..eb6ffca8c 100644 --- a/cli/src/test/java/de/jplag/cli/CommandLineInterfaceTest.java +++ b/cli/src/test/java/de/jplag/cli/CommandLineInterfaceTest.java @@ -1,18 +1,13 @@ package de.jplag.cli; -import static de.jplag.cli.CommandLineArgument.ROOT_DIRECTORY; -import static java.util.stream.Collectors.toSet; - -import java.util.Arrays; - import de.jplag.options.JPlagOptions; -import net.sourceforge.argparse4j.inf.Namespace; +import picocli.CommandLine; /** - * Test base for tests regarding the {@link CLI} and any {@link CommandLineArgument}. Solely tests if the arguments set - * via the command line interface are propagated correctly into options. JPlag is not executed for the different command - * line arguments, thus these tests do not test the functionality of the options during the comparison. + * Test base for tests regarding the {@link CLI}. Solely tests if the arguments set via the command line interface are + * propagated correctly into options. JPlag is not executed for the different command line arguments, thus these tests + * do not test the functionality of the options during the comparison. * @author Timur Saglam */ public abstract class CommandLineInterfaceTest { @@ -20,38 +15,30 @@ public abstract class CommandLineInterfaceTest { protected static final double DELTA = 1E-5; protected CLI cli; - protected Namespace namespace; protected JPlagOptions options; /** - * Creates a string for all arguments and their values that have been succesfully parsed. + * @return An empty {@link ArgumentBuilder} */ - private String parsedKeys(String... arguments) { - var keys = namespace.getAttrs().keySet().stream() - .filter(key -> key.equals(ROOT_DIRECTORY.flag()) || Arrays.stream(arguments).anyMatch(arg -> arg.contains("-" + key))); - return keys.map(it -> it.toString() + "=" + namespace.get(it)).collect(toSet()).toString(); + protected ArgumentBuilder arguments() { + return new ArgumentBuilder(); } /** - * Builds a CLI string for a CLI argument and a value. - * @param argument is the CLI argument. - * @param value is the value for that argument. - * @return "flag value" + * @return A {@link ArgumentBuilder} containing the CURRENT_DIRECTORY as the root directory */ - protected String buildArgument(CommandLineArgument argument, String value) { - return argument.flag() + "=" + value; + protected ArgumentBuilder defaultArguments() { + return arguments().rootDirectory(CURRENT_DIRECTORY); } /** - * Builds {@link JPlagOptions} via the command line interface. Sets {@link CommandLineInterfaceTest#cli}, - * {@link CommandLineInterfaceTest#namespace}, and {@link CommandLineInterfaceTest#options}. - * @param arguments are the command line interface arguments. + * Builds {@link JPlagOptions} via the command line interface. Sets {@link CommandLineInterfaceTest#cli} + * @param builder The argument builder containing the values to pass to the cli */ - protected void buildOptionsFromCLI(String... arguments) { + protected void buildOptionsFromCLI(ArgumentBuilder builder) throws CliException { cli = new CLI(); - namespace = cli.parseArguments(arguments); - System.out.println("Parsed arguments: " + parsedKeys(arguments)); - options = cli.buildOptionsFromArguments(namespace); + CommandLine.ParseResult result = cli.parseOptions(builder.getArgumentsAsArray()); + options = cli.buildOptionsFromArguments(result); } } diff --git a/cli/src/test/java/de/jplag/cli/CustomHelpTests.java b/cli/src/test/java/de/jplag/cli/CustomHelpTests.java new file mode 100644 index 000000000..3abde7505 --- /dev/null +++ b/cli/src/test/java/de/jplag/cli/CustomHelpTests.java @@ -0,0 +1,32 @@ +package de.jplag.cli; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import picocli.CommandLine; + +/** + * Tests for the {@link CustomHelp} class + */ +class CustomHelpTests { + private CommandLine.Help help; + + /** + * Creates the help object + */ + @BeforeEach + void setup() { + CommandLine.Model.CommandSpec commandSpec = CommandLine.Model.CommandSpec.create(); + this.help = new HelpFactory().create(commandSpec, new CommandLine(commandSpec).getColorScheme()); + } + + /** + * Tests, that the custom help object returns the custom label renderer + */ + @Test + void testReturnsCustomRenderer() { + Assertions.assertTrue(this.help.parameterLabelRenderer() instanceof ParamLabelRenderer, + "The custom help object returned the wrong ParamLabelRenderer type."); + } +} diff --git a/cli/src/test/java/de/jplag/cli/LanguageTest.java b/cli/src/test/java/de/jplag/cli/LanguageTest.java index 307d414e4..ed59a1a13 100644 --- a/cli/src/test/java/de/jplag/cli/LanguageTest.java +++ b/cli/src/test/java/de/jplag/cli/LanguageTest.java @@ -1,11 +1,11 @@ package de.jplag.cli; -import static com.github.stefanbirkner.systemlambda.SystemLambda.catchSystemExit; import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.Arrays; import java.util.List; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import de.jplag.Language; @@ -13,40 +13,37 @@ class LanguageTest extends CommandLineInterfaceTest { @Test - void testDefaultLanguage() { - buildOptionsFromCLI(CURRENT_DIRECTORY); - assertEquals(CommandLineArgument.DEFAULT_LANGUAGE_IDENTIFIER, options.language().getIdentifier()); + void testDefaultLanguage() throws CliException { + buildOptionsFromCLI(defaultArguments()); + assertEquals(CliOptions.defaultLanguage.getIdentifier(), options.language().getIdentifier()); } @Test - void testInvalidLanguage() throws Exception { - String argument = buildArgument(CommandLineArgument.LANGUAGE, "Piet"); - int statusCode = catchSystemExit(() -> buildOptionsFromCLI(argument, CURRENT_DIRECTORY)); - assertEquals(1, statusCode); + void testInvalidLanguage() { + Assertions.assertThrowsExactly(CliException.class, () -> buildOptionsFromCLI(defaultArguments().language("Piet"))); } @Test void testLoading() { var languages = LanguageLoader.getAllAvailableLanguages(); - assertEquals(14, languages.size(), "Loaded Languages: " + languages.keySet()); + assertEquals(18, languages.size(), "Loaded Languages: " + languages.keySet()); } @Test - void testValidLanguages() { + void testValidLanguages() throws CliException { for (Language language : LanguageLoader.getAllAvailableLanguages().values()) { - String argument = buildArgument(CommandLineArgument.LANGUAGE, language.getIdentifier()); - buildOptionsFromCLI(argument, CURRENT_DIRECTORY); + buildOptionsFromCLI(defaultArguments().language(language.getIdentifier())); + assertEquals(language.getIdentifier(), options.language().getIdentifier()); assertEquals(Arrays.asList(language.suffixes()), options.fileSuffixes()); } } @Test - void testCustomSuffixes() { - List suffixes = List.of("x", "y", "z"); - String argument = buildArgument(CommandLineArgument.SUFFIXES, String.join(",", suffixes)); - buildOptionsFromCLI(argument, CURRENT_DIRECTORY); - assertEquals(suffixes, options.fileSuffixes()); + void testCustomSuffixes() throws CliException { + String[] suffixes = {"x", "y", "z"}; + buildOptionsFromCLI(defaultArguments().suffixes(suffixes)); + assertEquals(List.of(suffixes), options.fileSuffixes()); } -} \ No newline at end of file +} diff --git a/cli/src/test/java/de/jplag/cli/MinTokenMatchTest.java b/cli/src/test/java/de/jplag/cli/MinTokenMatchTest.java index bedb17026..b1a0e13e9 100644 --- a/cli/src/test/java/de/jplag/cli/MinTokenMatchTest.java +++ b/cli/src/test/java/de/jplag/cli/MinTokenMatchTest.java @@ -1,47 +1,43 @@ package de.jplag.cli; -import static com.github.stefanbirkner.systemlambda.SystemLambda.catchSystemExit; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; class MinTokenMatchTest extends CommandLineInterfaceTest { @Test - void testLanguageDefault() { + void testLanguageDefault() throws CliException { // Language defaults not set yet: - buildOptionsFromCLI(CURRENT_DIRECTORY); + buildOptionsFromCLI(defaultArguments()); assertNotNull(options.language()); assertEquals(options.language().minimumTokenMatch(), options.minimumTokenMatch().intValue()); } @Test - void testInvalidInput() throws Exception { - String argument = buildArgument(CommandLineArgument.MIN_TOKEN_MATCH, "Not an integer..."); - int statusCode = catchSystemExit(() -> buildOptionsFromCLI(argument, CURRENT_DIRECTORY)); - assertEquals(1, statusCode); + void testInvalidInput() { + Assertions.assertThrowsExactly(CliException.class, () -> buildOptionsFromCLI(defaultArguments().minTokens("Not an integer..."))); } @Test - void testUpperBound() throws Exception { - String argument = buildArgument(CommandLineArgument.MIN_TOKEN_MATCH, "2147483648"); // max value plus one - int statusCode = catchSystemExit(() -> buildOptionsFromCLI(argument, CURRENT_DIRECTORY)); - assertEquals(1, statusCode); + void testUpperBound() { + String higherThanMax = String.valueOf(((long) Integer.MAX_VALUE) + 1); + + Assertions.assertThrowsExactly(CliException.class, () -> buildOptionsFromCLI(defaultArguments().minTokens(higherThanMax))); } @Test - void testLowerBound() { - String argument = buildArgument(CommandLineArgument.MIN_TOKEN_MATCH, Integer.toString(-1)); - buildOptionsFromCLI(argument, CURRENT_DIRECTORY); + void testLowerBound() throws CliException { + buildOptionsFromCLI(defaultArguments().minTokens(-1)); assertEquals(1, options.minimumTokenMatch().intValue()); } @Test - void testValidThreshold() { + void testValidThreshold() throws CliException { int expectedValue = 50; - String argument = buildArgument(CommandLineArgument.MIN_TOKEN_MATCH, Integer.toString(expectedValue)); - buildOptionsFromCLI(argument, CURRENT_DIRECTORY); + buildOptionsFromCLI(defaultArguments().minTokens(expectedValue)); assertEquals(expectedValue, options.minimumTokenMatch().intValue()); } } diff --git a/cli/src/test/java/de/jplag/cli/OldNewRootDirectoriesArgumentTest.java b/cli/src/test/java/de/jplag/cli/OldNewRootDirectoriesArgumentTest.java index 433fbd1ce..7e6967671 100644 --- a/cli/src/test/java/de/jplag/cli/OldNewRootDirectoriesArgumentTest.java +++ b/cli/src/test/java/de/jplag/cli/OldNewRootDirectoriesArgumentTest.java @@ -6,48 +6,48 @@ class OldNewRootDirectoriesArgumentTest extends CommandLineInterfaceTest { @Test - void testNoRootDirectories() { - buildOptionsFromCLI(); + void testNoRootDirectories() throws CliException { + buildOptionsFromCLI(arguments()); assertEquals(0, options.submissionDirectories().size()); assertEquals(0, options.oldSubmissionDirectories().size()); } @Test - void testTwoRootDirectoryArguments() { - buildOptionsFromCLI("root1", "root2"); + void testTwoRootDirectoryArguments() throws CliException { + buildOptionsFromCLI(arguments().rootDirectory("root1", "root2")); assertEquals(2, options.submissionDirectories().size()); assertEquals(0, options.oldSubmissionDirectories().size()); } @Test - void testNewOption() { - buildOptionsFromCLI("-new", "root1", "root2"); + void testNewOption() throws CliException { + buildOptionsFromCLI(arguments().newRootDirectories("root1", "root2")); assertEquals(2, options.submissionDirectories().size()); assertEquals(0, options.oldSubmissionDirectories().size()); } @Test - void testDoubleNewOption() { - buildOptionsFromCLI("-new", "root1", "-new", "root2"); + void testDoubleNewOption() throws CliException { + buildOptionsFromCLI(arguments().newRootDirectories("root1").newRootDirectories("root2")); assertEquals(2, options.submissionDirectories().size()); assertEquals(0, options.oldSubmissionDirectories().size()); } @Test - void testOldOption() { - buildOptionsFromCLI("-old", "root1"); + void testOldOption() throws CliException { + buildOptionsFromCLI(arguments().oldRootDirectories("root1")); assertEquals(0, options.submissionDirectories().size()); assertEquals(1, options.oldSubmissionDirectories().size()); } @Test - void testNewAndOldOption() { - buildOptionsFromCLI("-new", "root1", "-old", "root2"); + void testNewAndOldOption() throws CliException { + buildOptionsFromCLI(arguments().newRootDirectories("root2").oldRootDirectories("root2")); assertEquals(1, options.submissionDirectories().size()); assertEquals(1, options.oldSubmissionDirectories().size()); diff --git a/cli/src/test/java/de/jplag/cli/ParamLabelRendererTest.java b/cli/src/test/java/de/jplag/cli/ParamLabelRendererTest.java new file mode 100644 index 000000000..f10a2d350 --- /dev/null +++ b/cli/src/test/java/de/jplag/cli/ParamLabelRendererTest.java @@ -0,0 +1,82 @@ +package de.jplag.cli; + +import java.util.List; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import picocli.CommandLine; + +/** + * Tests for the custom {@link ParamLabelRenderer} + */ +class ParamLabelRendererTest { + private CommandLine.Help.IParamLabelRenderer paramLabelRenderer; + private CommandLine.Help.IParamLabelRenderer baseLabelRenderer; + + private CommandLine.Help.Ansi ansi; + private List styles; + + private static final String expectedEnumLabel = "=<{FIRST, SECOND, THIRD}>"; + + /** + * Creates the parameterLabelRenderer, the base renderer and formatting information for picocli. + */ + @BeforeEach + void setup() { + CommandLine commandLine = new CommandLine(CommandLine.Model.CommandSpec.create()); + CommandLine.Help help = commandLine.getHelp(); + + this.baseLabelRenderer = help.parameterLabelRenderer(); + this.paramLabelRenderer = new ParamLabelRenderer(this.baseLabelRenderer); + + this.ansi = help.ansi(); + this.styles = help.colorScheme().optionStyles(); + } + + /** + * Tests if enums are rendered correctly. + */ + @Test + void testRenderEnum() { + CommandLine.Model.ArgSpec argument = CommandLine.Model.OptionSpec.builder("enum").type(TestEnum.class).build(); + + String label = this.paramLabelRenderer.renderParameterLabel(argument, this.ansi, this.styles).plainString(); + Assertions.assertEquals(expectedEnumLabel, label); + } + + /** + * Tests, that a bunch of parameter types produces the same label as the default renderer from picocli + * @param parameterType The type for the option + */ + @ParameterizedTest + @ValueSource(classes = {Integer.class, String.class, Boolean.class}) + void testRenderDifferentTypes(Class parameterType) { + CommandLine.Model.ArgSpec argument = CommandLine.Model.OptionSpec.builder("test").type(parameterType).build(); + + String baseLabel = this.baseLabelRenderer.renderParameterLabel(argument, this.ansi, this.styles).plainString(); + String customLabel = this.paramLabelRenderer.renderParameterLabel(argument, this.ansi, this.styles).plainString(); + Assertions.assertEquals(baseLabel, customLabel); + } + + /** + * Tests that both the custom and the base label renderer return the same separator + */ + @Test + void testSameSeparator() { + Assertions.assertEquals(this.baseLabelRenderer.separator(), this.paramLabelRenderer.separator()); + } + + /** + * Enum used as for testing the label + */ + @SuppressWarnings("unused") + enum TestEnum { + FIRST, + SECOND, + THIRD + } +} diff --git a/cli/src/test/java/de/jplag/cli/SimilarityThresholdTest.java b/cli/src/test/java/de/jplag/cli/SimilarityThresholdTest.java new file mode 100644 index 000000000..f6f566b6f --- /dev/null +++ b/cli/src/test/java/de/jplag/cli/SimilarityThresholdTest.java @@ -0,0 +1,40 @@ +package de.jplag.cli; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; + +import org.junit.jupiter.api.Test; + +class SimilarityThresholdTest extends CommandLineInterfaceTest { + private static final double EXPECTED_DEFAULT_SIMILARITY_THRESHOLD = 0; + + @Test + void testDefaultThreshold() throws CliException { + buildOptionsFromCLI(defaultArguments()); + assertEquals(EXPECTED_DEFAULT_SIMILARITY_THRESHOLD, options.similarityThreshold()); + } + + @Test + void testInvalidThreshold() { + assertThrowsExactly(CliException.class, () -> buildOptionsFromCLI(defaultArguments().similarityThreshold("Not a Double..."))); + } + + @Test + void testLowerBound() throws CliException { + buildOptionsFromCLI(defaultArguments().similarityThreshold(-.01)); + assertEquals(0.0, options.similarityThreshold(), DELTA); + } + + @Test + void testUpperBound() throws CliException { + buildOptionsFromCLI(defaultArguments().similarityThreshold(1.01)); + assertEquals(1.0, options.similarityThreshold(), DELTA); + } + + @Test + void testValidThreshold() throws CliException { + double expectedValue = 0.5; + buildOptionsFromCLI(defaultArguments().similarityThreshold(expectedValue)); + assertEquals(expectedValue, options.similarityThreshold(), DELTA); + } +} diff --git a/cli/src/test/java/de/jplag/cli/SimiliarityThresholdTest.java b/cli/src/test/java/de/jplag/cli/SimiliarityThresholdTest.java deleted file mode 100644 index ea2870804..000000000 --- a/cli/src/test/java/de/jplag/cli/SimiliarityThresholdTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package de.jplag.cli; - -import static com.github.stefanbirkner.systemlambda.SystemLambda.catchSystemExit; -import static org.junit.jupiter.api.Assertions.assertEquals; - -import org.junit.jupiter.api.Test; - -import de.jplag.options.JPlagOptions; - -class SimiliarityThresholdTest extends CommandLineInterfaceTest { - - @Test - void testDefaultThreshold() { - buildOptionsFromCLI(CURRENT_DIRECTORY); - assertEquals(JPlagOptions.DEFAULT_SIMILARITY_THRESHOLD, options.similarityThreshold(), DELTA); - } - - @Test - void testInvalidThreshold() throws Exception { - String argument = buildArgument(CommandLineArgument.SIMILARITY_THRESHOLD, "Not a Double..."); - int statusCode = catchSystemExit(() -> buildOptionsFromCLI(argument, CURRENT_DIRECTORY)); - assertEquals(1.0, statusCode); - } - - @Test - void testLowerBound() { - String argument = buildArgument(CommandLineArgument.SIMILARITY_THRESHOLD, Double.toString(-0.01)); - buildOptionsFromCLI(argument, CURRENT_DIRECTORY); - assertEquals(0.0, options.similarityThreshold(), DELTA); - } - - @Test - void testUpperBound() { - String argument = buildArgument(CommandLineArgument.SIMILARITY_THRESHOLD, Double.toString(1.01)); - buildOptionsFromCLI(argument, CURRENT_DIRECTORY); - assertEquals(1.0, options.similarityThreshold(), DELTA); - } - - @Test - void testValidThreshold() { - double expectedValue = 0.5; - String argument = buildArgument(CommandLineArgument.SIMILARITY_THRESHOLD, Double.toString(expectedValue)); - buildOptionsFromCLI(argument, CURRENT_DIRECTORY); - assertEquals(expectedValue, options.similarityThreshold(), DELTA); - } -} diff --git a/cli/src/test/java/de/jplag/cli/StoredMatchesTest.java b/cli/src/test/java/de/jplag/cli/StoredMatchesTest.java index 9494f02b8..0004d269a 100644 --- a/cli/src/test/java/de/jplag/cli/StoredMatchesTest.java +++ b/cli/src/test/java/de/jplag/cli/StoredMatchesTest.java @@ -1,7 +1,7 @@ package de.jplag.cli; -import static com.github.stefanbirkner.systemlambda.SystemLambda.catchSystemExit; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; import org.junit.jupiter.api.Test; @@ -10,38 +10,33 @@ class StoredMatchesTest extends CommandLineInterfaceTest { @Test - void testDefault() { - buildOptionsFromCLI(CURRENT_DIRECTORY); + void testDefault() throws CliException { + buildOptionsFromCLI(defaultArguments()); assertEquals(JPlagOptions.DEFAULT_SHOWN_COMPARISONS, options.maximumNumberOfComparisons()); } @Test - void testValidThreshold() { + void testValidThreshold() throws CliException { int expectedValue = 999; - String argument = buildArgument(CommandLineArgument.SHOWN_COMPARISONS, Integer.toString(expectedValue)); - buildOptionsFromCLI(argument, CURRENT_DIRECTORY); + buildOptionsFromCLI(defaultArguments().shownComparisons(expectedValue)); assertEquals(expectedValue, options.maximumNumberOfComparisons()); } @Test - void testAll() { + void testAll() throws CliException { int expectedValue = JPlagOptions.SHOW_ALL_COMPARISONS; - String argument = buildArgument(CommandLineArgument.SHOWN_COMPARISONS, Integer.toString(expectedValue)); - buildOptionsFromCLI(argument, CURRENT_DIRECTORY); + buildOptionsFromCLI(defaultArguments().shownComparisons(expectedValue)); assertEquals(expectedValue, options.maximumNumberOfComparisons()); } @Test - void testLowerBound() { - String argument = buildArgument(CommandLineArgument.SHOWN_COMPARISONS, Integer.toString(-2)); - buildOptionsFromCLI(argument, CURRENT_DIRECTORY); + void testLowerBound() throws CliException { + buildOptionsFromCLI(defaultArguments().shownComparisons(-2)); assertEquals(JPlagOptions.SHOW_ALL_COMPARISONS, options.maximumNumberOfComparisons()); } @Test - void testInvalidThreshold() throws Exception { - String argument = buildArgument(CommandLineArgument.SHOWN_COMPARISONS, "Not an integer..."); - int statusCode = catchSystemExit(() -> buildOptionsFromCLI(argument, CURRENT_DIRECTORY)); - assertEquals(1, statusCode); + void testInvalidThreshold() { + assertThrowsExactly(CliException.class, () -> buildOptionsFromCLI(defaultArguments().shownComparisons("Not an integer..."))); } } diff --git a/core/pom.xml b/core/pom.xml index 41ef2caa5..0d1f9480c 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -11,6 +11,11 @@ jplag + + org.jgrapht + jgrapht-core + 1.5.2 + com.fasterxml.jackson.core jackson-databind diff --git a/core/src/main/java/de/jplag/GreedyStringTiling.java b/core/src/main/java/de/jplag/GreedyStringTiling.java index b91a61b62..19620ab56 100644 --- a/core/src/main/java/de/jplag/GreedyStringTiling.java +++ b/core/src/main/java/de/jplag/GreedyStringTiling.java @@ -1,6 +1,7 @@ package de.jplag; import java.util.ArrayList; +import java.util.Comparator; import java.util.HashSet; import java.util.IdentityHashMap; import java.util.List; @@ -8,8 +9,6 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import java.util.stream.Collectors; -import java.util.stream.IntStream; import de.jplag.options.JPlagOptions; @@ -24,14 +23,18 @@ public class GreedyStringTiling { private final int minimumMatchLength; - private ConcurrentMap tokenTypeValues; + private final JPlagOptions options; + private final ConcurrentMap tokenTypeValues; private final Map> baseCodeMarkings = new IdentityHashMap<>(); private final Map cachedTokenValueLists = new IdentityHashMap<>(); private final Map cachedHashLookupTables = new IdentityHashMap<>(); public GreedyStringTiling(JPlagOptions options) { - this.minimumMatchLength = options.minimumTokenMatch(); + this.options = options; + // Ensures 1 <= neighborLength <= minimumTokenMatch + int minimumNeighborLength = Math.min(Math.max(options.mergingOptions().minimumNeighborLength(), 1), options.minimumTokenMatch()); + this.minimumMatchLength = options.mergingOptions().enabled() ? minimumNeighborLength : options.minimumTokenMatch(); this.tokenTypeValues = new ConcurrentHashMap<>(); this.tokenTypeValues.put(SharedTokenType.FILE_END, 0); } @@ -75,12 +78,13 @@ public final JPlagComparison generateBaseCodeMarking(Submission submission, Subm public final JPlagComparison compare(Submission firstSubmission, Submission secondSubmission) { Submission smallerSubmission; Submission largerSubmission; - if (firstSubmission.getTokenList().size() > secondSubmission.getTokenList().size()) { - smallerSubmission = secondSubmission; - largerSubmission = firstSubmission; - } else { + Comparator comp = Comparator.comparing((Submission s) -> s.getTokenList().size()).thenComparing(Submission::getName); + if (comp.compare(firstSubmission, secondSubmission) <= 0) { smallerSubmission = firstSubmission; largerSubmission = secondSubmission; + } else { + smallerSubmission = secondSubmission; + largerSubmission = firstSubmission; } return compareInternal(smallerSubmission, largerSubmission); } @@ -92,43 +96,36 @@ public final JPlagComparison compare(Submission firstSubmission, Submission seco * @return the comparison results. */ private JPlagComparison compareInternal(Submission leftSubmission, Submission rightSubmission) { - List leftTokens = leftSubmission.getTokenList(); - List rightTokens = rightSubmission.getTokenList(); - int[] leftValues = tokenValueListFromSubmission(leftSubmission); int[] rightValues = tokenValueListFromSubmission(rightSubmission); - // comparison uses <= because it is assumed that the last token is a pivot (FILE_END) - if (leftTokens.size() <= minimumMatchLength || rightTokens.size() <= minimumMatchLength) { - return new JPlagComparison(leftSubmission, rightSubmission, List.of()); - } - - Set leftMarkedIndexes = initiallyMarkedTokenIndexes(leftSubmission); - Set rightMarkedIndexes = initiallyMarkedTokenIndexes(rightSubmission); + boolean[] leftMarked = calculateInitiallyMarked(leftSubmission); + boolean[] rightMarked = calculateInitiallyMarked(rightSubmission); - SubsequenceHashLookupTable leftLookupTable = subsequenceHashLookupTableForSubmission(leftSubmission, leftMarkedIndexes); - SubsequenceHashLookupTable rightLookupTable = subsequenceHashLookupTableForSubmission(rightSubmission, rightMarkedIndexes); + SubsequenceHashLookupTable leftLookupTable = subsequenceHashLookupTableForSubmission(leftSubmission, leftMarked); + SubsequenceHashLookupTable rightLookupTable = subsequenceHashLookupTableForSubmission(rightSubmission, rightMarked); int maximumMatchLength; List globalMatches = new ArrayList<>(); + List ignoredMatches = new ArrayList<>(); do { maximumMatchLength = minimumMatchLength; List iterationMatches = new ArrayList<>(); for (int leftStartIndex = 0; leftStartIndex < leftValues.length - maximumMatchLength; leftStartIndex++) { int leftSubsequenceHash = leftLookupTable.subsequenceHashForStartIndex(leftStartIndex); - if (leftMarkedIndexes.contains(leftStartIndex) || leftSubsequenceHash == SubsequenceHashLookupTable.NO_HASH) { + if (leftMarked[leftStartIndex] || leftSubsequenceHash == SubsequenceHashLookupTable.NO_HASH) { continue; } List possiblyMatchingRightStartIndexes = rightLookupTable .startIndexesOfPossiblyMatchingSubsequencesForSubsequenceHash(leftSubsequenceHash); for (Integer rightStartIndex : possiblyMatchingRightStartIndexes) { // comparison uses >= because it is assumed that the last token is a pivot (FILE_END) - if (rightMarkedIndexes.contains(rightStartIndex) || maximumMatchLength >= rightValues.length - rightStartIndex) { + if (rightMarked[rightStartIndex] || maximumMatchLength >= rightValues.length - rightStartIndex) { continue; } - int subsequenceMatchLength = maximalMatchingSubsequenceLengthNotMarked(leftValues, leftStartIndex, leftMarkedIndexes, rightValues, - rightStartIndex, rightMarkedIndexes, maximumMatchLength); + int subsequenceMatchLength = maximalMatchingSubsequenceLengthNotMarked(leftValues, leftStartIndex, leftMarked, rightValues, + rightStartIndex, rightMarked, maximumMatchLength); if (subsequenceMatchLength >= maximumMatchLength) { if (subsequenceMatchLength > maximumMatchLength) { iterationMatches.clear(); @@ -140,16 +137,20 @@ private JPlagComparison compareInternal(Submission leftSubmission, Submission ri } } for (Match match : iterationMatches) { - addMatchIfNotOverlapping(globalMatches, match); + if (match.length() < options.minimumTokenMatch()) { + addMatchIfNotOverlapping(ignoredMatches, match); + } else { + addMatchIfNotOverlapping(globalMatches, match); + } int leftStartIndex = match.startOfFirst(); int rightStartIndex = match.startOfSecond(); for (int offset = 0; offset < match.length(); offset++) { - leftMarkedIndexes.add(leftStartIndex + offset); - rightMarkedIndexes.add(rightStartIndex + offset); + leftMarked[leftStartIndex + offset] = true; + rightMarked[rightStartIndex + offset] = true; } } } while (maximumMatchLength != minimumMatchLength); - return new JPlagComparison(leftSubmission, rightSubmission, globalMatches); + return new JPlagComparison(leftSubmission, rightSubmission, globalMatches, ignoredMatches); } /** @@ -158,27 +159,26 @@ private JPlagComparison compareInternal(Submission leftSubmission, Submission ri * the assumption that the further tokens are away, the more likely they differ. * @param leftValues The list of left values. * @param leftStartIndex The start index in the left list. - * @param leftMarkedIndexes The marked indexes of the left list. + * @param leftMarked Which left values are marked. * @param rightValues The list of right values. * @param rightStartIndex The start index in the right list. - * @param rightMarkedIndexes The marked indexes of the right list. + * @param rightMarked Which right values are marked. * @param minimumSequenceLength The minimal sequence length for a matching subsequence. Must be not negative. * @return the maximal matching subsequence length, or 0 if there is no subsequence of at least the minimum sequence * length. */ - private int maximalMatchingSubsequenceLengthNotMarked(int[] leftValues, int leftStartIndex, Set leftMarkedIndexes, int[] rightValues, - int rightStartIndex, Set rightMarkedIndexes, int minimumSequenceLength) { + private int maximalMatchingSubsequenceLengthNotMarked(int[] leftValues, int leftStartIndex, boolean[] leftMarked, int[] rightValues, + int rightStartIndex, boolean[] rightMarked, int minimumSequenceLength) { for (int offset = minimumSequenceLength - 1; offset >= 0; offset--) { int leftIndex = leftStartIndex + offset; int rightIndex = rightStartIndex + offset; - if (leftValues[leftIndex] != rightValues[rightIndex] || leftMarkedIndexes.contains(leftIndex) - || rightMarkedIndexes.contains(rightIndex)) { + if (leftValues[leftIndex] != rightValues[rightIndex] || leftMarked[leftIndex] || rightMarked[rightIndex]) { return 0; } } int offset = minimumSequenceLength; - while (leftValues[leftStartIndex + offset] == rightValues[rightStartIndex + offset] && !leftMarkedIndexes.contains(leftStartIndex + offset) - && !rightMarkedIndexes.contains(rightStartIndex + offset)) { + while (leftValues[leftStartIndex + offset] == rightValues[rightStartIndex + offset] && !leftMarked[leftStartIndex + offset] + && !rightMarked[rightStartIndex + offset]) { offset++; } return offset; @@ -193,17 +193,19 @@ private void addMatchIfNotOverlapping(List matches, Match match) { matches.add(match); } - private Set initiallyMarkedTokenIndexes(Submission submission) { + private boolean[] calculateInitiallyMarked(Submission submission) { Set baseCodeTokens = baseCodeMarkings.get(submission); List tokens = submission.getTokenList(); - return IntStream.range(0, tokens.size()) - .filter(i -> tokens.get(i).getType().isExcludedFromMatching() || (baseCodeTokens != null && baseCodeTokens.contains(tokens.get(i)))) - .boxed().collect(Collectors.toSet()); + boolean[] result = new boolean[tokens.size()]; + for (int i = 0; i < result.length; i++) { + result[i] = tokens.get(i).getType().isExcludedFromMatching() || (baseCodeTokens != null && baseCodeTokens.contains(tokens.get(i))); + } + return result; } - private SubsequenceHashLookupTable subsequenceHashLookupTableForSubmission(Submission submission, Set markedIndexes) { + private SubsequenceHashLookupTable subsequenceHashLookupTableForSubmission(Submission submission, boolean[] marked) { return cachedHashLookupTables.computeIfAbsent(submission, - (key -> new SubsequenceHashLookupTable(minimumMatchLength, tokenValueListFromSubmission(key), markedIndexes))); + (key -> new SubsequenceHashLookupTable(minimumMatchLength, tokenValueListFromSubmission(key), marked))); } /** diff --git a/core/src/main/java/de/jplag/JPlag.java b/core/src/main/java/de/jplag/JPlag.java index 137e6b11c..16bafb1da 100644 --- a/core/src/main/java/de/jplag/JPlag.java +++ b/core/src/main/java/de/jplag/JPlag.java @@ -1,5 +1,7 @@ package de.jplag; +import java.io.File; +import java.util.List; import java.util.ResourceBundle; import org.slf4j.Logger; @@ -8,6 +10,7 @@ import de.jplag.clustering.ClusteringFactory; import de.jplag.exceptions.ExitException; import de.jplag.exceptions.SubmissionException; +import de.jplag.merging.MatchMerging; import de.jplag.options.JPlagOptions; import de.jplag.reporting.reportobject.model.Version; import de.jplag.strategy.ComparisonStrategy; @@ -30,42 +33,67 @@ private static Version loadVersion() { private final JPlagOptions options; - private final Language language; - private final ComparisonStrategy comparisonStrategy; - /** * Creates and initializes a JPlag instance, parameterized by a set of options. + * @deprecated in favor of static {@link #run(JPlagOptions)}. * @param options determines the parameterization. */ + @Deprecated(since = "4.3.0") public JPlag(JPlagOptions options) { this.options = options; - language = this.options.language(); - GreedyStringTiling coreAlgorithm = new GreedyStringTiling(options); - comparisonStrategy = new ParallelComparisonStrategy(options, coreAlgorithm); } /** * Main procedure, executes the comparison of source code submissions. + * @deprecated in favor of static {@link #run(JPlagOptions)}. * @return the results of the comparison, specifically the submissions whose similarity exceeds a set threshold. - * @throws ExitException if the JPlag exits preemptively. + * @throws ExitException if JPlag exits preemptively. */ + @Deprecated(since = "4.3.0") public JPlagResult run() throws ExitException { + return run(options); + } + + /** + * Main procedure, executes the comparison of source code submissions. + * @param options determines the parameterization. + * @return the results of the comparison, specifically the submissions whose similarity exceeds a set threshold. + * @throws ExitException if JPlag exits preemptively. + */ + public static JPlagResult run(JPlagOptions options) throws ExitException { + GreedyStringTiling coreAlgorithm = new GreedyStringTiling(options); + ComparisonStrategy comparisonStrategy = new ParallelComparisonStrategy(options, coreAlgorithm); // Parse and validate submissions. - SubmissionSetBuilder builder = new SubmissionSetBuilder(language, options); + SubmissionSetBuilder builder = new SubmissionSetBuilder(options); SubmissionSet submissionSet = builder.buildSubmissionSet(); - int submissionCount = submissionSet.numberOfSubmissions(); - if (submissionCount < 2) { + if (submissionCount < 2) throw new SubmissionException("Not enough valid submissions! (found " + submissionCount + " valid submissions)"); - } // Compare valid submissions. JPlagResult result = comparisonStrategy.compareSubmissions(submissionSet); + + // Use Match Merging against obfuscation + if (options.mergingOptions().enabled()) { + result = new MatchMerging(options).mergeMatchesOf(result); + } + if (logger.isInfoEnabled()) logger.info("Total time for comparing submissions: {}", TimeUtil.formatDuration(result.getDuration())); - result.setClusteringResult(ClusteringFactory.getClusterings(result.getAllComparisons(), options.clusteringOptions())); + logSkippedSubmissions(submissionSet, options); + return result; } + + private static void logSkippedSubmissions(SubmissionSet submissionSet, JPlagOptions options) { + List skippedSubmissions = submissionSet.getInvalidSubmissions(); + if (!skippedSubmissions.isEmpty()) { + logger.warn("{} submissions were skipped (see errors above): {}", skippedSubmissions.size(), skippedSubmissions); + if (options.debugParser()) { + logger.warn("Erroneous submissions were copied to {}", new File(JPlagOptions.ERROR_FOLDER).getAbsolutePath()); + } + } + } } diff --git a/core/src/main/java/de/jplag/JPlagComparison.java b/core/src/main/java/de/jplag/JPlagComparison.java index 7f69d1b1d..37aa0c7ad 100644 --- a/core/src/main/java/de/jplag/JPlagComparison.java +++ b/core/src/main/java/de/jplag/JPlagComparison.java @@ -9,17 +9,18 @@ * @param secondSubmission is the second of the two submissions. * @param matches is the unmodifiable list of all matches between the two submissions. */ -public record JPlagComparison(Submission firstSubmission, Submission secondSubmission, List matches) { +public record JPlagComparison(Submission firstSubmission, Submission secondSubmission, List matches, List ignoredMatches) { /** * Initializes a new comparison. * @param firstSubmission is the first of the two submissions. * @param secondSubmission is the second of the two submissions. * @param matches is the list of all matches between the two submissions. */ - public JPlagComparison(Submission firstSubmission, Submission secondSubmission, List matches) { + public JPlagComparison(Submission firstSubmission, Submission secondSubmission, List matches, List ignoredMatches) { this.firstSubmission = firstSubmission; this.secondSubmission = secondSubmission; this.matches = Collections.unmodifiableList(matches); + this.ignoredMatches = Collections.unmodifiableList(ignoredMatches); } /** diff --git a/core/src/main/java/de/jplag/JPlagResult.java b/core/src/main/java/de/jplag/JPlagResult.java index 8b4d123d9..2b1aabd32 100644 --- a/core/src/main/java/de/jplag/JPlagResult.java +++ b/core/src/main/java/de/jplag/JPlagResult.java @@ -23,7 +23,7 @@ public class JPlagResult { private final int[] similarityDistribution; // 10-element array representing the similarity distribution of the detected matches. private List> clusteringResult; - private final int SIMILARITY_DISTRIBUTION_SIZE = 10; + private final int SIMILARITY_DISTRIBUTION_SIZE = 100; public JPlagResult(List comparisons, SubmissionSet submissions, long durationInMillis, JPlagOptions options) { // sort by similarity (descending) diff --git a/core/src/main/java/de/jplag/Submission.java b/core/src/main/java/de/jplag/Submission.java index 576af0fbd..f47db6d60 100644 --- a/core/src/main/java/de/jplag/Submission.java +++ b/core/src/main/java/de/jplag/Submission.java @@ -4,26 +4,26 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import de.jplag.normalization.TokenStringNormalizer; +import de.jplag.options.JPlagOptions; + /** * Represents a single submission. A submission can contain multiple files. */ public class Submission implements Comparable { private static final Logger logger = LoggerFactory.getLogger(Submission.class); - /** - * Directory name for storing submission files with parse errors if so requested. - */ - private static final String ERROR_FOLDER = "errors"; - /** * Identification of the submission (often a directory or file name). */ @@ -222,7 +222,7 @@ private void copySubmission() { } private static File createErrorDirectory(String... subdirectoryNames) { - File subdirectory = Path.of(ERROR_FOLDER, subdirectoryNames).toFile(); + File subdirectory = Path.of(JPlagOptions.ERROR_FOLDER, subdirectoryNames).toFile(); if (!subdirectory.exists()) { subdirectory.mkdirs(); } @@ -248,7 +248,7 @@ private static File createErrorDirectory(String... subdirectoryNames) { try { tokenList = language.parse(new HashSet<>(files)); } catch (ParsingException e) { - logger.warn("Failed to parse submission {} with error {}", this, e); + logger.warn("Failed to parse submission {} with error {}", this, e.getMessage(), e); tokenList = null; hasErrors = true; if (debugParser) { @@ -265,4 +265,43 @@ private static File createErrorDirectory(String... subdirectoryNames) { } return true; } + + /** + * Perform token string normalization, which makes the token string invariant to dead code insertion and independent + * statement reordering. + */ + void normalize() { + List originalOrder = getOrder(tokenList); + TokenStringNormalizer.normalize(tokenList); + List normalizedOrder = getOrder(tokenList); + + logger.debug("original line order: {}", originalOrder); + logger.debug("line order after normalization: {}", normalizedOrder); + Set normalizedSet = new HashSet<>(normalizedOrder); + List removed = originalOrder.stream().filter(l -> !normalizedSet.contains(l)).toList(); + logger.debug("removed {} line(s): {}", removed.size(), removed); + } + + private List getOrder(List tokenList) { + List order = new ArrayList<>(tokenList.size()); // a little too big + int currentLineNumber = tokenList.get(0).getLine(); + order.add(currentLineNumber); + for (Token token : tokenList) { + if (token.getLine() != currentLineNumber) { + currentLineNumber = token.getLine(); + order.add(currentLineNumber); + } + } + return order; + } + + /** + * @return Submission containing shallow copies of its fields. + */ + public Submission copy() { + Submission copy = new Submission(name, submissionRootFile, isNew, files, language); + copy.setTokenList(new ArrayList<>(tokenList)); + copy.setBaseCodeComparison(baseCodeComparison); + return copy; + } } diff --git a/core/src/main/java/de/jplag/SubmissionSet.java b/core/src/main/java/de/jplag/SubmissionSet.java index 5fd637324..c9fbc6f11 100644 --- a/core/src/main/java/de/jplag/SubmissionSet.java +++ b/core/src/main/java/de/jplag/SubmissionSet.java @@ -90,6 +90,10 @@ public List getInvalidSubmissions() { return invalidSubmissions; } + public void normalizeSubmissions() { + submissions.forEach(Submission::normalize); + } + private List filterValidSubmissions() { return allSubmissions.stream().filter(submission -> !submission.hasErrors()).collect(Collectors.toCollection(ArrayList::new)); } @@ -118,7 +122,8 @@ private void parseBaseCodeSubmission(Submission baseCode) throws BasecodeExcepti if (!baseCode.parse(options.debugParser())) { throw new BasecodeException("Could not successfully parse basecode submission!"); } else if (baseCode.getNumberOfTokens() < options.minimumTokenMatch()) { - throw new BasecodeException("Basecode submission contains fewer tokens than minimum match length allows!"); + throw new BasecodeException(String.format("Basecode submission contains %d token(s), which is less than the minimum match length (%d)!", + baseCode.getNumberOfTokens(), options.minimumTokenMatch())); } logger.trace("Basecode submission parsed!"); long duration = System.currentTimeMillis() - startTime; @@ -149,7 +154,8 @@ private void parseSubmissions(List submissions) { } if (submission.getTokenList() != null && submission.getNumberOfTokens() < options.minimumTokenMatch()) { - logger.error("Submission {} contains fewer tokens than minimum match length allows!", currentSubmissionName); + logger.error("Submission {} contains {} token(s), which is less than the minimum match length ({})!", currentSubmissionName, + submission.getNumberOfTokens(), options.minimumTokenMatch()); submission.setTokenList(null); tooShort++; ok = false; diff --git a/core/src/main/java/de/jplag/SubmissionSetBuilder.java b/core/src/main/java/de/jplag/SubmissionSetBuilder.java index ff567e847..4d93c0d44 100644 --- a/core/src/main/java/de/jplag/SubmissionSetBuilder.java +++ b/core/src/main/java/de/jplag/SubmissionSetBuilder.java @@ -31,19 +31,25 @@ public class SubmissionSetBuilder { private static final Logger logger = LoggerFactory.getLogger(SubmissionSetBuilder.class); - private final Language language; private final JPlagOptions options; - private final Set excludedFileNames; // Set of file names to be excluded in comparison. /** * Creates a builder for submission sets. + * @deprecated in favor of {@link #SubmissionSetBuilder(JPlagOptions)}. * @param language is the language of the submissions. * @param options are the configured options. */ + @Deprecated(since = "4.3.0") public SubmissionSetBuilder(Language language, JPlagOptions options) { - this.language = language; + this(options.withLanguageOption(language)); + } + + /** + * Creates a builder for submission sets. + * @param options are the configured options. + */ + public SubmissionSetBuilder(JPlagOptions options) { this.options = options; - this.excludedFileNames = options.excludedFiles(); } /** @@ -75,6 +81,13 @@ public SubmissionSet buildSubmissionSet() throws ExitException { // Merge everything in a submission set. List submissions = new ArrayList<>(foundSubmissions.values()); + + // Some languages expect a certain order, which is ensured here: + if (options.language().expectsSubmissionOrder()) { + List rootFiles = foundSubmissions.values().stream().map(it -> it.getRoot()).toList(); + rootFiles = options.language().customizeSubmissionOrder(rootFiles); + submissions = new ArrayList<>(rootFiles.stream().map(foundSubmissions::get).toList()); + } return new SubmissionSet(submissions, baseCodeSubmission.orElse(null), options); } @@ -209,7 +222,7 @@ private Submission processSubmission(String submissionName, File submissionFile, } submissionFile = makeCanonical(submissionFile, it -> new SubmissionException("Cannot create submission: " + submissionName, it)); - return new Submission(submissionName, submissionFile, isNew, parseFilesRecursively(submissionFile), language); + return new Submission(submissionName, submissionFile, isNew, parseFilesRecursively(submissionFile), options.language()); } /** @@ -254,7 +267,7 @@ private boolean hasValidSuffix(File file) { * Checks if a file is excluded or not. */ private boolean isFileExcluded(File file) { - return excludedFileNames.stream().anyMatch(excludedName -> file.getName().endsWith(excludedName)); + return options.excludedFiles().stream().anyMatch(excludedName -> file.getName().endsWith(excludedName)); } /** diff --git a/core/src/main/java/de/jplag/SubsequenceHashLookupTable.java b/core/src/main/java/de/jplag/SubsequenceHashLookupTable.java index 7260b7c02..aa44c783b 100644 --- a/core/src/main/java/de/jplag/SubsequenceHashLookupTable.java +++ b/core/src/main/java/de/jplag/SubsequenceHashLookupTable.java @@ -4,7 +4,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; /** * A class to generate and store hashes over a fixed length subsequence of a given list of values. Hash generation is @@ -30,10 +29,9 @@ class SubsequenceHashLookupTable { * Generates a new subsequence hash lookup table. Performance is optimized to compute hashes in O(n). * @param windowSize the size of the subsequences. * @param values the values to hash over. - * @param markedIndexes the indexes of marked values. Subsequences containing a marked value obtain the {@link #NO_HASH} - * value. + * @param marked Which values are marked. Subsequences containing a marked value obtain the {@link #NO_HASH} value. */ - SubsequenceHashLookupTable(int windowSize, int[] values, Set markedIndexes) { + SubsequenceHashLookupTable(int windowSize, int[] values, boolean[] marked) { windowSize = Math.max(1, windowSize); windowSize = Math.min(MAX_HASH_LENGTH, windowSize); this.windowSize = windowSize; @@ -45,7 +43,7 @@ class SubsequenceHashLookupTable { subsequenceHashes = new int[values.length - windowSize]; startIndexToSubsequenceHashesMap = new HashMap<>(subsequenceHashes.length); - computeSubsequenceHashes(markedIndexes); + computeSubsequenceHashes(marked); } /** Returns the size of the subsequences used for hashing */ @@ -82,10 +80,10 @@ List startIndexesOfPossiblyMatchingSubsequencesForSubsequenceHash(int s /** * Creates hashes for all subsequences with windowSize. Code is optimized to perform in O(n) using a windowing approach. * Hashes are computed by \sum from (i=0 to windowSize) with hash(values[offset+i]) * 2^(hashLength-1-i) - * @param markedIndexes contains the indexes of marked values. Subsequences containing a marked value will receive the + * @param marked contains which of the values are marked. Subsequences containing a marked value will receive the * {@link #NO_HASH} value. */ - private void computeSubsequenceHashes(Set markedIndexes) { + private void computeSubsequenceHashes(boolean[] marked) { int hash = 0; int hashedLength = 0; int factor = (windowSize != 1 ? (2 << (windowSize - 2)) : 1); @@ -102,7 +100,7 @@ private void computeSubsequenceHashes(Set markedIndexes) { hash -= factor * hashValueForValue(values[windowStartIndex]); } hash = (2 * hash) + hashValueForValue(values[windowEndIndex]); - if (markedIndexes.contains(windowEndIndex)) { + if (marked[windowEndIndex]) { hashedLength = 0; } else { hashedLength++; diff --git a/core/src/main/java/de/jplag/TimeUtil.java b/core/src/main/java/de/jplag/TimeUtil.java index 077ef9a75..3cafcd992 100644 --- a/core/src/main/java/de/jplag/TimeUtil.java +++ b/core/src/main/java/de/jplag/TimeUtil.java @@ -1,5 +1,7 @@ package de.jplag; +import java.time.Duration; + public final class TimeUtil { private TimeUtil() { @@ -12,10 +14,8 @@ private TimeUtil() { * @return Readable representation of the time interval. */ public static String formatDuration(long durationInMilliseconds) { - int timeInSeconds = (int) (durationInMilliseconds / 1000); - String hours = (timeInSeconds / 3600 > 0) ? (timeInSeconds / 3600) + " h " : ""; - String minutes = (timeInSeconds / 60 > 0) ? ((timeInSeconds / 60) % 60) + " min " : ""; - String seconds = (timeInSeconds % 60) + " sec"; - return hours + minutes + seconds; + Duration duration = Duration.ofMillis(durationInMilliseconds); + return String.format("%dh %02dmin %02ds %03dms", duration.toHours(), duration.toMinutesPart(), duration.toSecondsPart(), + duration.toMillisPart()); } } diff --git a/core/src/main/java/de/jplag/clustering/ClusteringFactory.java b/core/src/main/java/de/jplag/clustering/ClusteringFactory.java index d2a889493..7351493e1 100644 --- a/core/src/main/java/de/jplag/clustering/ClusteringFactory.java +++ b/core/src/main/java/de/jplag/clustering/ClusteringFactory.java @@ -31,6 +31,10 @@ public class ClusteringFactory { private static final Logger logger = LoggerFactory.getLogger(ClusteringFactory.class); public static List> getClusterings(Collection comparisons, ClusteringOptions options) { + if (comparisons.isEmpty()) { + return Collections.emptyList(); + } + if (!options.enabled()) { logger.warn(CLUSTERING_DISABLED); return Collections.emptyList(); diff --git a/core/src/main/java/de/jplag/merging/MatchMerging.java b/core/src/main/java/de/jplag/merging/MatchMerging.java new file mode 100644 index 000000000..108530a7e --- /dev/null +++ b/core/src/main/java/de/jplag/merging/MatchMerging.java @@ -0,0 +1,203 @@ +package de.jplag.merging; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import de.jplag.JPlagComparison; +import de.jplag.JPlagResult; +import de.jplag.Match; +import de.jplag.SharedTokenType; +import de.jplag.Submission; +import de.jplag.Token; +import de.jplag.options.JPlagOptions; + +/** + * This class implements a match merging algorithm which serves as a defense mechanism against obfuscation attacks. + * Based on configurable parameters MinimumNeighborLength and MaximumGapSize, it alters prior results from pairwise + * submission comparisons and merges all neighboring matches that fit the specified thresholds. Submissions are referred + * to as left and right and neighboring matches as upper and lower. When neighboring matches get merged they become one + * and the tokens separating them get removed from the submission clone. MinimumNeighborLength describes how short a + * match can be and MaximumGapSize describes how many tokens can be between two neighboring matches. Both are set in + * {@link JPlagOptions} as {@link MergingOptions} and default to (2,6). + */ +public class MatchMerging { + private JPlagOptions options; + + /** + * Instantiates the match merging algorithm for a comparison result and a set of specific options. + * @param options encapsulates the adjustable options + */ + public MatchMerging(JPlagOptions options) { + this.options = options; + } + + /** + * Runs the internal match merging pipeline. It computes neighboring matches, merges them based on + * {@link MergingOptions} and removes remaining too short matches afterwards. + * @param result is the initially computed result object + * @return JPlagResult containing the merged matches + */ + public JPlagResult mergeMatchesOf(JPlagResult result) { + long timeBeforeStartInMillis = System.currentTimeMillis(); + + List comparisons = new ArrayList<>(result.getAllComparisons()); + List comparisonsMerged = new ArrayList<>(); + + for (JPlagComparison comparison : comparisons) { + Submission leftSubmission = comparison.firstSubmission().copy(); + Submission rightSubmission = comparison.secondSubmission().copy(); + List globalMatches = new ArrayList<>(comparison.matches()); + globalMatches.addAll(comparison.ignoredMatches()); + globalMatches = removeTooShortMatches(mergeNeighbors(globalMatches, leftSubmission, rightSubmission)); + comparisonsMerged.add(new JPlagComparison(leftSubmission, rightSubmission, globalMatches, new ArrayList<>())); + } + + long durationInMillis = System.currentTimeMillis() - timeBeforeStartInMillis; + return new JPlagResult(comparisonsMerged, result.getSubmissions(), result.getDuration() + durationInMillis, options); + } + + /** + * Computes neighbors by sorting based on order of matches in the left and right submissions and then checking which are + * next to each other in both. + * @param globalMatches + * @return neighbors containing a list of pairs of neighboring matches + */ + private List computeNeighbors(List globalMatches) { + List neighbors = new ArrayList<>(); + List sortedByLeft = new ArrayList<>(globalMatches); + Collections.sort(sortedByLeft, (match1, match2) -> match1.startOfFirst() - match2.startOfFirst()); + List sortedByRight = new ArrayList<>(globalMatches); + Collections.sort(sortedByRight, (match1, match2) -> match1.startOfSecond() - match2.startOfSecond()); + for (int i = 0; i < sortedByLeft.size() - 1; i++) { + if (sortedByRight.indexOf(sortedByLeft.get(i)) == (sortedByRight.indexOf(sortedByLeft.get(i + 1)) - 1)) { + neighbors.add(new Neighbor(sortedByLeft.get(i), sortedByLeft.get(i + 1))); + } + } + return neighbors; + } + + /** + * This function iterates through the neighboring matches and checks which fit the merging criteria. Those who do are + * merged and the original matches are removed. This is done, until there are either no neighbors left, or none fit the + * criteria + * @return globalMatches containing merged matches. + */ + private List mergeNeighbors(List globalMatches, Submission leftSubmission, Submission rightSubmission) { + int i = 0; + List neighbors = computeNeighbors(globalMatches); + + while (i < neighbors.size()) { + Match upperNeighbor = neighbors.get(i).upperMatch(); + Match lowerNeighbor = neighbors.get(i).lowerMatch(); + + int lengthUpper = upperNeighbor.length(); + int lengthLower = lowerNeighbor.length(); + int tokenBetweenLeft = lowerNeighbor.startOfFirst() - upperNeighbor.endOfFirst() - 1; + int tokensBetweenRight = lowerNeighbor.startOfSecond() - upperNeighbor.endOfSecond() - 1; + double averageTokensBetweenMatches = (tokenBetweenLeft + tokensBetweenRight) / 2.0; + // Checking length is not necessary as GST already checked length while computing matches + if (averageTokensBetweenMatches <= options.mergingOptions().maximumGapSize() + && !mergeOverlapsFiles(leftSubmission, rightSubmission, upperNeighbor, tokenBetweenLeft, tokensBetweenRight)) { + globalMatches.remove(upperNeighbor); + globalMatches.remove(lowerNeighbor); + globalMatches.add(new Match(upperNeighbor.startOfFirst(), upperNeighbor.startOfSecond(), lengthUpper + lengthLower)); + globalMatches = removeToken(globalMatches, leftSubmission, rightSubmission, upperNeighbor, tokenBetweenLeft, tokensBetweenRight); + neighbors = computeNeighbors(globalMatches); + i = 0; + } else { + i++; + } + } + return globalMatches; + } + + /** + * This function checks if a merge would go over file boundaries. + * @param leftSubmission is the left submission + * @param rightSubmission is the right submission + * @param upperNeighbor is the upper neighboring match + * @param tokensBetweenLeft amount of token that separate the neighboring matches in the left submission and need to be + * removed + * @param tokensBetweenRight amount token that separate the neighboring matches in the send submission and need to be + * removed + * @return true if the merge goes over file boundaries. + */ + private boolean mergeOverlapsFiles(Submission leftSubmission, Submission rightSubmission, Match upperNeighbor, int tokensBetweenLeft, + int tokensBetweenRight) { + if (leftSubmission.getFiles().size() == 1 && rightSubmission.getFiles().size() == 1) { + return false; + } + int startLeft = upperNeighbor.startOfFirst(); + int startRight = upperNeighbor.startOfSecond(); + int lengthUpper = upperNeighbor.length(); + + List tokenLeft = new ArrayList<>(leftSubmission.getTokenList()); + List tokenRight = new ArrayList<>(rightSubmission.getTokenList()); + tokenLeft = tokenLeft.subList(startLeft + lengthUpper, startLeft + lengthUpper + tokensBetweenLeft); + tokenRight = tokenRight.subList(startRight + lengthUpper, startRight + lengthUpper + tokensBetweenRight); + + return containsFileEndToken(tokenLeft) || containsFileEndToken(tokenRight); + } + + /** + * This function checks whether a list of token contains FILE_END + * @param token is the list of token + * @return true if FILE_END is in token + */ + private boolean containsFileEndToken(List token) { + return token.stream().map(Token::getType).anyMatch(it -> it.equals(SharedTokenType.FILE_END)); + } + + /** + * This function removes token from both submissions after a merge has been performed. Additionally it moves the + * starting positions from matches, that occur after the merged neighboring matches, by the amount of removed token. + * @param globalMatches + * @param leftSubmission is the left submission + * @param rightSubmission is the right submission + * @param upperNeighbor is the upper neighboring match + * @param tokensBetweenLeft amount of token that separate the neighboring matches in the left submission and need to be + * removed + * @param tokensBetweenRight amount token that separate the neighboring matches in the send submission and need to be + * removed + * @return shiftedMatches with the mentioned changes. + */ + private List removeToken(List globalMatches, Submission leftSubmission, Submission rightSubmission, Match upperNeighbor, + int tokensBetweenLeft, int tokensBetweenRight) { + int startLeft = upperNeighbor.startOfFirst(); + int startRight = upperNeighbor.startOfSecond(); + int lengthUpper = upperNeighbor.length(); + + List tokenLeft = new ArrayList<>(leftSubmission.getTokenList()); + List tokenRight = new ArrayList<>(rightSubmission.getTokenList()); + tokenLeft.subList(startLeft + lengthUpper, startLeft + lengthUpper + tokensBetweenLeft).clear(); + tokenRight.subList(startRight + lengthUpper, startRight + lengthUpper + tokensBetweenRight).clear(); + leftSubmission.setTokenList(tokenLeft); + rightSubmission.setTokenList(tokenRight); + + List shiftedMatches = new ArrayList<>(); + for (Match match : globalMatches) { + int leftShift = match.startOfFirst() > startLeft ? tokensBetweenLeft : 0; + int rightShift = match.startOfSecond() > startRight ? tokensBetweenRight : 0; + Match alteredMatch = new Match(match.startOfFirst() - leftShift, match.startOfSecond() - rightShift, match.length()); + shiftedMatches.add(alteredMatch); + } + + return shiftedMatches; + } + + /** + * This method marks the end of the merging pipeline and removes the remaining too short matches from + * @param globalMatches + */ + private List removeTooShortMatches(List globalMatches) { + List toRemove = new ArrayList<>(); + for (Match match : globalMatches) { + if (match.length() < options.minimumTokenMatch()) { + toRemove.add(match); + } + } + globalMatches.removeAll(toRemove); + return globalMatches; + } +} \ No newline at end of file diff --git a/core/src/main/java/de/jplag/merging/MergingOptions.java b/core/src/main/java/de/jplag/merging/MergingOptions.java new file mode 100644 index 000000000..fc340e293 --- /dev/null +++ b/core/src/main/java/de/jplag/merging/MergingOptions.java @@ -0,0 +1,44 @@ +package de.jplag.merging; + +/** + * Collection of parameters that describe how a match merging should be performed. + * @param minimumNeighborLength describes how short a match can be, to be considered (Defaults to 2). + * @param maximumGapSize describes how many tokens can be between to neighboring matches (Defaults to 6). + */ +public record MergingOptions(boolean enabled, int minimumNeighborLength, int maximumGapSize) { + + /** + * The default values of MergingOptions are false for the enable-switch, which deactivate MatchMerging, while + * minimumNeighborLength and maximumGapSize default to (2,6), which in testing yielded the best results. + */ + public MergingOptions() { + this(false, 2, 6); + } + + /** + * Builder pattern method for setting enabled + * @param enabled containing the new value + * @return MergingOptions with specified enabled + */ + public MergingOptions withEnabled(boolean enabled) { + return new MergingOptions(enabled, minimumNeighborLength, maximumGapSize); + } + + /** + * Builder pattern method for setting minimumNeighborLength + * @param minimumNeighborLength containing the new value + * @return MergingOptions with specified minimumNeighborLength + */ + public MergingOptions withMinimumNeighborLength(int minimumNeighborLength) { + return new MergingOptions(enabled, minimumNeighborLength, maximumGapSize); + } + + /** + * Builder pattern method for setting maximumGapSize + * @param maximumGapSize containing the new value + * @return MergingOptions with specified maximumGapSize + */ + public MergingOptions withMaximumGapSize(int maximumGapSize) { + return new MergingOptions(enabled, minimumNeighborLength, maximumGapSize); + } +} diff --git a/core/src/main/java/de/jplag/merging/Neighbor.java b/core/src/main/java/de/jplag/merging/Neighbor.java new file mode 100644 index 000000000..dc9052b18 --- /dev/null +++ b/core/src/main/java/de/jplag/merging/Neighbor.java @@ -0,0 +1,10 @@ +package de.jplag.merging; + +import de.jplag.Match; + +/** + * This class realizes a pair of neighboring matches, named upperMatch and lowerMatch. Two matches are considered + * neighbors, if they begin directly after one another in the left submission and in the right submission. + */ +public record Neighbor(Match upperMatch, Match lowerMatch) { +} \ No newline at end of file diff --git a/core/src/main/java/de/jplag/normalization/Edge.java b/core/src/main/java/de/jplag/normalization/Edge.java new file mode 100644 index 000000000..5f6922db3 --- /dev/null +++ b/core/src/main/java/de/jplag/normalization/Edge.java @@ -0,0 +1,6 @@ +package de.jplag.normalization; + +import de.jplag.semantics.Variable; + +record Edge(EdgeType type, Variable cause) { +} diff --git a/core/src/main/java/de/jplag/normalization/EdgeType.java b/core/src/main/java/de/jplag/normalization/EdgeType.java new file mode 100644 index 000000000..f75b30ffe --- /dev/null +++ b/core/src/main/java/de/jplag/normalization/EdgeType.java @@ -0,0 +1,29 @@ +package de.jplag.normalization; + +/** + * Enum for types of edges in normalization graph. Given two statements S and T, S comes before T, there is such an edge + * between S and T if... + */ +enum EdgeType { + /** + * S writes a variable T reads. + */ + VARIABLE_FLOW, + /** + * S reads a variable T writes, and S and T are in the same bidirectional block. + */ + VARIABLE_REVERSE_FLOW, + /** + * S and T access the same variable, and at least one of the two accesses is not a read. + */ + VARIABLE_ORDER, + /** + * S or T have full position significance, and there is no statement C with full position significance between them. + */ + POSITION_SIGNIFICANCE_FULL, + /** + * S and T have partial position significance, and there is no statement C with partial position significance between + * them. + */ + POSITION_SIGNIFICANCE_PARTIAL +} diff --git a/core/src/main/java/de/jplag/normalization/MultipleEdge.java b/core/src/main/java/de/jplag/normalization/MultipleEdge.java new file mode 100644 index 000000000..6265c5371 --- /dev/null +++ b/core/src/main/java/de/jplag/normalization/MultipleEdge.java @@ -0,0 +1,36 @@ +package de.jplag.normalization; + +import java.util.HashSet; +import java.util.Set; + +import de.jplag.semantics.Variable; + +/** + * Models a multiple edge in the normalization graph. Contains multiple edges. + */ +class MultipleEdge { + private Set edges; + private boolean isVariableFlow; + private boolean isVariableReverseFlow; + + MultipleEdge() { + edges = new HashSet<>(); + isVariableFlow = false; + } + + boolean isVariableFlow() { + return isVariableFlow; + } + + boolean isVariableReverseFlow() { + return isVariableReverseFlow; + } + + void addEdge(EdgeType type, Variable cause) { + if (type == EdgeType.VARIABLE_FLOW) + isVariableFlow = true; + if (type == EdgeType.VARIABLE_REVERSE_FLOW) + isVariableReverseFlow = true; + edges.add(new Edge(type, cause)); + } +} diff --git a/core/src/main/java/de/jplag/normalization/NormalizationGraphConstructor.java b/core/src/main/java/de/jplag/normalization/NormalizationGraphConstructor.java new file mode 100644 index 000000000..a5f4e496e --- /dev/null +++ b/core/src/main/java/de/jplag/normalization/NormalizationGraphConstructor.java @@ -0,0 +1,133 @@ +package de.jplag.normalization; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.jgrapht.graph.SimpleDirectedGraph; + +import de.jplag.Token; +import de.jplag.semantics.Variable; + +/** + * Constructs the normalization graph. + */ +class NormalizationGraphConstructor { + private SimpleDirectedGraph graph; + private int bidirectionalBlockDepth; + private Collection fullPositionSignificanceIncoming; + private Statement lastFullPositionSignificance; + private Statement lastPartialPositionSignificance; + private Map> variableReads; + private Map> variableWrites; + private Set inCurrentBidirectionalBlock; + private Statement current; + + NormalizationGraphConstructor(List tokens) { + graph = new SimpleDirectedGraph<>(MultipleEdge.class); + bidirectionalBlockDepth = 0; + fullPositionSignificanceIncoming = new ArrayList<>(); + variableReads = new HashMap<>(); + variableWrites = new HashMap<>(); + inCurrentBidirectionalBlock = new HashSet<>(); + StatementBuilder builderForCurrent = new StatementBuilder(tokens.get(0).getLine()); + for (Token token : tokens) { + if (token.getLine() != builderForCurrent.lineNumber()) { + addStatement(builderForCurrent.build()); + builderForCurrent = new StatementBuilder(token.getLine()); + } + builderForCurrent.addToken(token); + } + addStatement(builderForCurrent.build()); + } + + SimpleDirectedGraph get() { + return graph; + } + + private void addStatement(Statement statement) { + graph.addVertex(statement); + this.current = statement; + processBidirectionalBlock(); + processFullPositionSignificance(); + processPartialPositionSignificance(); + processReads(); + processWrites(); + for (Variable variable : current.semantics().reads()) + addVariableToMap(variableReads, variable); + for (Variable variable : current.semantics().writes()) + addVariableToMap(variableWrites, variable); + } + + private void processBidirectionalBlock() { + bidirectionalBlockDepth += current.semantics().bidirectionalBlockDepthChange(); + if (bidirectionalBlockDepth > 0) + inCurrentBidirectionalBlock.add(current); + else + inCurrentBidirectionalBlock.clear(); + } + + private void processFullPositionSignificance() { + if (current.semantics().hasFullPositionSignificance()) { + for (Statement node : fullPositionSignificanceIncoming) + addIncomingEdgeToCurrent(node, EdgeType.POSITION_SIGNIFICANCE_FULL, null); + fullPositionSignificanceIncoming.clear(); + lastFullPositionSignificance = current; + } else if (lastFullPositionSignificance != null) { + addIncomingEdgeToCurrent(lastFullPositionSignificance, EdgeType.POSITION_SIGNIFICANCE_FULL, null); + } + fullPositionSignificanceIncoming.add(current); + } + + private void processPartialPositionSignificance() { + if (current.semantics().hasPartialPositionSignificance()) { + if (lastPartialPositionSignificance != null) { + addIncomingEdgeToCurrent(lastPartialPositionSignificance, EdgeType.POSITION_SIGNIFICANCE_PARTIAL, null); + } + lastPartialPositionSignificance = current; + } + } + + private void processReads() { + for (Variable variable : current.semantics().reads()) { + for (Statement node : variableWrites.getOrDefault(variable, Set.of())) + addIncomingEdgeToCurrent(node, EdgeType.VARIABLE_FLOW, variable); + } + } + + private void processWrites() { + for (Variable variable : current.semantics().writes()) { + for (Statement node : variableWrites.getOrDefault(variable, Set.of())) + addIncomingEdgeToCurrent(node, EdgeType.VARIABLE_ORDER, variable); + for (Statement node : variableReads.getOrDefault(variable, Set.of())) { + EdgeType edgeType = inCurrentBidirectionalBlock.contains(node) ? // + EdgeType.VARIABLE_REVERSE_FLOW : EdgeType.VARIABLE_ORDER; + addIncomingEdgeToCurrent(node, edgeType, variable); + } + } + } + + /** + * Adds an incoming edge to the current node. + * @param start the start of the edge + * @param type the type of the edge + * @param cause the variable that caused the edge, may be null + */ + private void addIncomingEdgeToCurrent(Statement start, EdgeType type, Variable cause) { + MultipleEdge multipleEdge = graph.getEdge(start, current); + if (multipleEdge == null) { + multipleEdge = new MultipleEdge(); + graph.addEdge(start, current, multipleEdge); + } + multipleEdge.addEdge(type, cause); + } + + private void addVariableToMap(Map> variableMap, Variable variable) { + variableMap.putIfAbsent(variable, new ArrayList<>()); + variableMap.get(variable).add(current); + } +} diff --git a/core/src/main/java/de/jplag/normalization/Statement.java b/core/src/main/java/de/jplag/normalization/Statement.java new file mode 100644 index 000000000..c7086bb74 --- /dev/null +++ b/core/src/main/java/de/jplag/normalization/Statement.java @@ -0,0 +1,74 @@ +package de.jplag.normalization; + +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import de.jplag.Token; +import de.jplag.semantics.CodeSemantics; + +/** + * Models statements, which are the nodes of the normalization graph. + */ +class Statement implements Comparable { + + private final List tokens; + private final int lineNumber; + private final CodeSemantics semantics; + + Statement(List tokens, int lineNumber) { + this.tokens = Collections.unmodifiableList(tokens); + this.lineNumber = lineNumber; + this.semantics = CodeSemantics.join(tokens.stream().map(Token::getSemantics).toList()); + } + + List tokens() { + return tokens; + } + + CodeSemantics semantics() { + return semantics; + } + + void markKeep() { + semantics.markKeep(); + } + + private int tokenOrdinal(Token token) { + return ((Enum) token.getType()).ordinal(); // reflects the order the enums were declared in + } + + @Override + public int compareTo(Statement other) { + int sizeComp = Integer.compare(this.tokens.size(), other.tokens.size()); + if (sizeComp != 0) + return -sizeComp; // bigger size should come first + Iterator myTokens = this.tokens.iterator(); + Iterator otherTokens = other.tokens.iterator(); + for (int i = 0; i < this.tokens.size(); i++) { + int tokenComp = Integer.compare(tokenOrdinal(myTokens.next()), tokenOrdinal(otherTokens.next())); + if (tokenComp != 0) + return tokenComp; + } + return 0; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null || getClass() != obj.getClass()) + return false; + return tokens.equals(((Statement) obj).tokens); + } + + @Override + public int hashCode() { + return tokens.hashCode(); + } + + @Override + public String toString() { + return lineNumber + ": " + String.join(" ", tokens.stream().map(Token::toString).toList()); + } +} diff --git a/core/src/main/java/de/jplag/normalization/StatementBuilder.java b/core/src/main/java/de/jplag/normalization/StatementBuilder.java new file mode 100644 index 000000000..1afaa3eb3 --- /dev/null +++ b/core/src/main/java/de/jplag/normalization/StatementBuilder.java @@ -0,0 +1,32 @@ +package de.jplag.normalization; + +import java.util.ArrayList; +import java.util.List; + +import de.jplag.Token; + +/** + * Builds statements, which are the nodes of the normalization graph. + */ +class StatementBuilder { + + private List tokens; + private final int lineNumber; + + StatementBuilder(int lineNumber) { + this.lineNumber = lineNumber; + this.tokens = new ArrayList<>(); + } + + int lineNumber() { + return lineNumber; + } + + void addToken(Token token) { + tokens.add(token); + } + + Statement build() { + return new Statement(tokens, lineNumber); + } +} diff --git a/core/src/main/java/de/jplag/normalization/TokenStringNormalizer.java b/core/src/main/java/de/jplag/normalization/TokenStringNormalizer.java new file mode 100644 index 000000000..47a053d0f --- /dev/null +++ b/core/src/main/java/de/jplag/normalization/TokenStringNormalizer.java @@ -0,0 +1,74 @@ +package de.jplag.normalization; + +import java.util.LinkedList; +import java.util.List; +import java.util.PriorityQueue; +import java.util.Queue; +import java.util.stream.Collectors; + +import org.jgrapht.Graphs; +import org.jgrapht.graph.SimpleDirectedGraph; + +import de.jplag.Token; + +/** + * Performs token string normalization. + */ +public class TokenStringNormalizer { + + private TokenStringNormalizer() { + } + + /** + * Normalizes the token string it receives in place. Tokens representing dead code have been eliminated and tokens + * representing subsequent independent statements have been put in a fixed order. Works by first constructing a + * Normalization Graph and then turning it back into a token string. + */ + public static void normalize(List tokens) { + SimpleDirectedGraph normalizationGraph = new NormalizationGraphConstructor(tokens).get(); + tokens.clear(); + spreadKeep(normalizationGraph); + PriorityQueue roots = normalizationGraph.vertexSet().stream() // + .filter(v -> !Graphs.vertexHasPredecessors(normalizationGraph, v)) // + .collect(Collectors.toCollection(PriorityQueue::new)); + while (!roots.isEmpty()) { + PriorityQueue newRoots = new PriorityQueue<>(); + do { + Statement statement = roots.poll(); + if (statement.semantics().keep()) { + tokens.addAll(statement.tokens()); + } + for (Statement successor : Graphs.successorListOf(normalizationGraph, statement)) { + normalizationGraph.removeEdge(statement, successor); + if (!Graphs.vertexHasPredecessors(normalizationGraph, successor)) { + newRoots.add(successor); + } + } + } while (!roots.isEmpty()); + roots = newRoots; + } + } + + /** + * Spread keep status to every node that does not represent dead code. Nodes without keep status are later eliminated. + */ + private static void spreadKeep(SimpleDirectedGraph normalizationGraph) { + Queue visit = new LinkedList<>(normalizationGraph.vertexSet().stream() // + .filter(tl -> tl.semantics().keep()).toList()); + while (!visit.isEmpty()) { + Statement current = visit.remove(); + for (Statement predecessor : Graphs.predecessorListOf(normalizationGraph, current)) { // performance of iteration? + if (!predecessor.semantics().keep() && normalizationGraph.getEdge(predecessor, current).isVariableFlow()) { + predecessor.markKeep(); + visit.add(predecessor); + } + } + for (Statement successor : Graphs.successorListOf(normalizationGraph, current)) { + if (!successor.semantics().keep() && normalizationGraph.getEdge(current, successor).isVariableReverseFlow()) { + successor.markKeep(); + visit.add(successor); + } + } + } + } +} diff --git a/core/src/main/java/de/jplag/options/JPlagOptions.java b/core/src/main/java/de/jplag/options/JPlagOptions.java index e392fefdf..44eea1d2f 100644 --- a/core/src/main/java/de/jplag/options/JPlagOptions.java +++ b/core/src/main/java/de/jplag/options/JPlagOptions.java @@ -2,7 +2,6 @@ import java.io.BufferedReader; import java.io.File; -import java.io.FileReader; import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; @@ -20,6 +19,8 @@ import de.jplag.Language; import de.jplag.clustering.ClusteringOptions; import de.jplag.exceptions.BasecodeException; +import de.jplag.merging.MergingOptions; +import de.jplag.util.FileUtils; /** * This record defines the options to configure {@link JPlag}. @@ -47,25 +48,26 @@ public record JPlagOptions(Language language, Integer minimumTokenMatch, Set submissionDirectories, Set oldSubmissionDirectories, File baseCodeSubmissionDirectory, String subdirectoryName, List fileSuffixes, String exclusionFileName, SimilarityMetric similarityMetric, double similarityThreshold, int maximumNumberOfComparisons, ClusteringOptions clusteringOptions, - boolean debugParser) { + boolean debugParser, MergingOptions mergingOptions) { public static final double DEFAULT_SIMILARITY_THRESHOLD = 0; public static final int DEFAULT_SHOWN_COMPARISONS = 100; public static final int SHOW_ALL_COMPARISONS = 0; public static final SimilarityMetric DEFAULT_SIMILARITY_METRIC = SimilarityMetric.AVG; public static final Charset CHARSET = StandardCharsets.UTF_8; + public static final String ERROR_FOLDER = "errors"; private static final Logger logger = LoggerFactory.getLogger(JPlagOptions.class); public JPlagOptions(Language language, Set submissionDirectories, Set oldSubmissionDirectories) { this(language, null, submissionDirectories, oldSubmissionDirectories, null, null, null, null, DEFAULT_SIMILARITY_METRIC, - DEFAULT_SIMILARITY_THRESHOLD, DEFAULT_SHOWN_COMPARISONS, new ClusteringOptions(), false); + DEFAULT_SIMILARITY_THRESHOLD, DEFAULT_SHOWN_COMPARISONS, new ClusteringOptions(), false, new MergingOptions()); } public JPlagOptions(Language language, Integer minimumTokenMatch, Set submissionDirectories, Set oldSubmissionDirectories, File baseCodeSubmissionDirectory, String subdirectoryName, List fileSuffixes, String exclusionFileName, SimilarityMetric similarityMetric, double similarityThreshold, int maximumNumberOfComparisons, ClusteringOptions clusteringOptions, - boolean debugParser) { + boolean debugParser, MergingOptions mergingOptions) { this.language = language; this.debugParser = debugParser; this.fileSuffixes = fileSuffixes == null || fileSuffixes.isEmpty() ? null : Collections.unmodifiableList(fileSuffixes); @@ -79,84 +81,91 @@ public JPlagOptions(Language language, Integer minimumTokenMatch, Set subm this.baseCodeSubmissionDirectory = baseCodeSubmissionDirectory; this.subdirectoryName = subdirectoryName; this.clusteringOptions = clusteringOptions; + this.mergingOptions = mergingOptions; } public JPlagOptions withLanguageOption(Language language) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions); } public JPlagOptions withDebugParser(boolean debugParser) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions); } public JPlagOptions withFileSuffixes(List fileSuffixes) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions); } public JPlagOptions withSimilarityThreshold(double similarityThreshold) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions); } public JPlagOptions withMaximumNumberOfComparisons(int maximumNumberOfComparisons) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions); } public JPlagOptions withSimilarityMetric(SimilarityMetric similarityMetric) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions); } public JPlagOptions withMinimumTokenMatch(Integer minimumTokenMatch) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions); } public JPlagOptions withExclusionFileName(String exclusionFileName) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions); } public JPlagOptions withSubmissionDirectories(Set submissionDirectories) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions); } public JPlagOptions withOldSubmissionDirectories(Set oldSubmissionDirectories) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions); } public JPlagOptions withBaseCodeSubmissionDirectory(File baseCodeSubmissionDirectory) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions); } public JPlagOptions withSubdirectoryName(String subdirectoryName) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions); } public JPlagOptions withClusteringOptions(ClusteringOptions clusteringOptions) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions); + } + + public JPlagOptions withMergingOptions(MergingOptions mergingOptions) { + return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, + subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, + clusteringOptions, debugParser, mergingOptions); } public boolean hasBaseCode() { @@ -184,7 +193,7 @@ public Integer minimumTokenMatch() { } private Set readExclusionFile(final String exclusionFileName) { - try (BufferedReader reader = new BufferedReader(new FileReader(exclusionFileName, JPlagOptions.CHARSET))) { + try (BufferedReader reader = FileUtils.openFileReader(new File(exclusionFileName))) { final var excludedFileNames = reader.lines().collect(Collectors.toSet()); if (logger.isDebugEnabled()) { logger.debug("Excluded files:{}{}", System.lineSeparator(), String.join(System.lineSeparator(), excludedFileNames)); @@ -245,10 +254,10 @@ private Integer normalizeMinimumTokenMatch(Integer minimumTokenMatch) { public JPlagOptions(Language language, Integer minimumTokenMatch, File submissionDirectory, Set oldSubmissionDirectories, String baseCodeSubmissionName, String subdirectoryName, List fileSuffixes, String exclusionFileName, SimilarityMetric similarityMetric, double similarityThreshold, int maximumNumberOfComparisons, ClusteringOptions clusteringOptions, - boolean debugParser) throws BasecodeException { + boolean debugParser, MergingOptions mergingOptions) throws BasecodeException { this(language, minimumTokenMatch, Set.of(submissionDirectory), oldSubmissionDirectories, convertLegacyBaseCodeToFile(baseCodeSubmissionName, submissionDirectory), subdirectoryName, fileSuffixes, exclusionFileName, - similarityMetric, similarityThreshold, maximumNumberOfComparisons, clusteringOptions, debugParser); + similarityMetric, similarityThreshold, maximumNumberOfComparisons, clusteringOptions, debugParser, mergingOptions); } /** @@ -271,7 +280,7 @@ public JPlagOptions withBaseCodeSubmissionName(String baseCodeSubmissionName) { try { return new JPlagOptions(language, minimumTokenMatch, submissionDirectory, oldSubmissionDirectories, baseCodeSubmissionName, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions); } catch (BasecodeException e) { throw new IllegalArgumentException(e.getMessage(), e.getCause()); } @@ -297,11 +306,7 @@ private static File convertLegacyBaseCodeToFile(String baseCodeSubmissionName, F while (normalizedName.endsWith(File.separator)) { normalizedName = normalizedName.substring(0, normalizedName.length() - 1); } - if (normalizedName.isEmpty() || normalizedName.contains(File.separator)) { - throw new BasecodeException( - "The basecode directory name \"" + normalizedName + "\" cannot contain dots! Please migrate to the path-based API."); - } - if (normalizedName.contains(".")) { + if (normalizedName.isEmpty() || normalizedName.contains(File.separator) || normalizedName.contains(".")) { throw new BasecodeException( "The basecode directory name \"" + normalizedName + "\" cannot contain dots! Please migrate to the path-based API."); } diff --git a/core/src/main/java/de/jplag/reporting/FilePathUtil.java b/core/src/main/java/de/jplag/reporting/FilePathUtil.java new file mode 100644 index 000000000..d2db74ad7 --- /dev/null +++ b/core/src/main/java/de/jplag/reporting/FilePathUtil.java @@ -0,0 +1,29 @@ +package de.jplag.reporting; + +import java.io.File; +import java.nio.file.Path; +import java.util.function.Function; + +import de.jplag.Submission; + +public final class FilePathUtil { + + private FilePathUtil() { + // private constructor to prevent instantiation + } + + /** + * Returns the files path relative to the root folder of the submission ID + * @param file File that should be relativized + * @param submission Submission file belongs to + * @param submissionToIdFunction Function to map names to ids + * @return Relative path + */ + public static String getRelativeSubmissionPath(File file, Submission submission, Function submissionToIdFunction) { + if (file.toPath().equals(submission.getRoot().toPath())) { + return Path.of(submissionToIdFunction.apply(submission), submissionToIdFunction.apply(submission)).toString(); + } + return Path.of(submissionToIdFunction.apply(submission), submission.getRoot().toPath().relativize(file.toPath()).toString()).toString(); + } + +} diff --git a/core/src/main/java/de/jplag/reporting/jsonfactory/ComparisonReportWriter.java b/core/src/main/java/de/jplag/reporting/jsonfactory/ComparisonReportWriter.java index 7fda46f69..242d09138 100644 --- a/core/src/main/java/de/jplag/reporting/jsonfactory/ComparisonReportWriter.java +++ b/core/src/main/java/de/jplag/reporting/jsonfactory/ComparisonReportWriter.java @@ -1,10 +1,9 @@ package de.jplag.reporting.jsonfactory; -import java.io.File; -import java.nio.file.Path; import java.util.Comparator; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; @@ -13,6 +12,8 @@ import de.jplag.JPlagResult; import de.jplag.Submission; import de.jplag.Token; +import de.jplag.options.SimilarityMetric; +import de.jplag.reporting.FilePathUtil; import de.jplag.reporting.reportobject.model.ComparisonReport; import de.jplag.reporting.reportobject.model.Match; @@ -55,7 +56,8 @@ private void writeComparisons(String path, List comparisons) { String secondSubmissionId = submissionToIdFunction.apply(comparison.secondSubmission()); String fileName = generateComparisonName(firstSubmissionId, secondSubmissionId); addToLookUp(firstSubmissionId, secondSubmissionId, fileName); - var comparisonReport = new ComparisonReport(firstSubmissionId, secondSubmissionId, comparison.similarity(), + var comparisonReport = new ComparisonReport(firstSubmissionId, secondSubmissionId, + Map.of(SimilarityMetric.AVG.name(), comparison.similarity(), SimilarityMetric.MAX.name(), comparison.maximalSimilarity()), convertMatchesToReportMatches(comparison)); fileWriter.saveAsJSON(comparisonReport, path, fileName); }); @@ -103,16 +105,13 @@ private Match convertMatchToReportMatch(JPlagComparison comparison, de.jplag.Mat Token startOfSecond = tokensSecond.stream().min(lineComparator).orElseThrow(); Token endOfSecond = tokensSecond.stream().max(lineComparator).orElseThrow(); - return new Match(relativizedFilePath(startOfFirst.getFile(), comparison.firstSubmission()), - relativizedFilePath(startOfSecond.getFile(), comparison.secondSubmission()), startOfFirst.getLine(), endOfFirst.getLine(), - startOfSecond.getLine(), endOfSecond.getLine(), match.length()); - } + List firstTotalTokens = tokensFirst.stream().filter(x -> Objects.equals(x.getFile(), startOfFirst.getFile())).toList(); + List secondTotalTokens = tokensSecond.stream().filter(x -> Objects.equals(x.getFile(), startOfSecond.getFile())).toList(); - private String relativizedFilePath(File file, Submission submission) { - if (file.toPath().equals(submission.getRoot().toPath())) { - return Path.of(submissionToIdFunction.apply(submission), submissionToIdFunction.apply(submission)).toString(); - } - return Path.of(submissionToIdFunction.apply(submission), submission.getRoot().toPath().relativize(file.toPath()).toString()).toString(); + return new Match(FilePathUtil.getRelativeSubmissionPath(startOfFirst.getFile(), comparison.firstSubmission(), submissionToIdFunction), + FilePathUtil.getRelativeSubmissionPath(startOfSecond.getFile(), comparison.secondSubmission(), submissionToIdFunction), + startOfFirst.getLine(), endOfFirst.getLine(), startOfSecond.getLine(), endOfSecond.getLine(), match.length(), firstTotalTokens.size(), + secondTotalTokens.size()); } } diff --git a/core/src/main/java/de/jplag/reporting/reportobject/ReportObjectFactory.java b/core/src/main/java/de/jplag/reporting/reportobject/ReportObjectFactory.java index 0e2db6c91..0f8f142da 100644 --- a/core/src/main/java/de/jplag/reporting/reportobject/ReportObjectFactory.java +++ b/core/src/main/java/de/jplag/reporting/reportobject/ReportObjectFactory.java @@ -12,6 +12,8 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; +import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @@ -26,12 +28,13 @@ import de.jplag.JPlagResult; import de.jplag.Language; import de.jplag.Submission; +import de.jplag.reporting.FilePathUtil; import de.jplag.reporting.jsonfactory.ComparisonReportWriter; import de.jplag.reporting.jsonfactory.ToDiskWriter; import de.jplag.reporting.reportobject.mapper.ClusteringResultMapper; import de.jplag.reporting.reportobject.mapper.MetricMapper; -import de.jplag.reporting.reportobject.model.Metric; import de.jplag.reporting.reportobject.model.OverviewReport; +import de.jplag.reporting.reportobject.model.SubmissionFileIndex; import de.jplag.reporting.reportobject.model.Version; /** @@ -39,11 +42,14 @@ * to the disk. */ public class ReportObjectFactory { + private static final String DIRECTORY_ERROR = "Could not create directory {} for report viewer generation"; + private static final Logger logger = LoggerFactory.getLogger(ReportObjectFactory.class); private static final ToDiskWriter fileWriter = new ToDiskWriter(); public static final String OVERVIEW_FILE_NAME = "overview.json"; public static final String SUBMISSIONS_FOLDER = "files"; + public static final String SUBMISSION_FILE_INDEX_FILE_NAME = "submissionFileIndex.json"; public static final Version REPORT_VIEWER_VERSION = JPlag.JPLAG_VERSION; private Map submissionNameToIdMap; @@ -66,11 +72,12 @@ public void createAndSaveReport(JPlagResult result, String path) { writeComparisons(result, path); writeOverview(result, path); + writeSubmissionIndexFile(result, path); logger.info("Zipping report files..."); zipAndDelete(path); } catch (IOException e) { - logger.error("Could not create directory " + path + " for report viewer generation", e); + logger.error(DIRECTORY_ERROR, e, path); } } @@ -124,7 +131,7 @@ private File createSubmissionDirectory(String path, File submissionsPath, Submis try { return createDirectory(submissionsPath.getPath(), submissionToIdFunction.apply(submission), file, submissionRoot); } catch (IOException e) { - logger.error("Could not create directory " + path + " for report viewer generation", e); + logger.error(DIRECTORY_ERROR, e, path); return null; } } @@ -133,7 +140,7 @@ private File createSubmissionDirectory(String path, File submissionsPath, Submis try { return createDirectory(submissionsPath.getPath(), submissionToIdFunction.apply(submission)); } catch (IOException e) { - logger.error("Could not create directory " + path + " for report viewer generation", e); + logger.error(DIRECTORY_ERROR, e, path); return null; } } @@ -142,7 +149,7 @@ private File createSubmissionsDirectory(String path) { try { return createDirectory(path, SUBMISSIONS_FOLDER); } catch (IOException e) { - logger.error("Could not create directory " + path + " for report viewer generation", e); + logger.error(DIRECTORY_ERROR, e, path); return null; } } @@ -167,7 +174,7 @@ private void writeOverview(JPlagResult result, String path) { int totalComparisons = result.getAllComparisons().size(); int numberOfMaximumComparisons = result.getOptions().maximumNumberOfComparisons(); - int shownComparisons = totalComparisons > numberOfMaximumComparisons ? numberOfMaximumComparisons : totalComparisons; + int shownComparisons = Math.min(totalComparisons, numberOfMaximumComparisons); int missingComparisons = totalComparisons > numberOfMaximumComparisons ? (totalComparisons - numberOfMaximumComparisons) : 0; logger.info("Total Comparisons: {}. Comparisons in Report: {}. Omitted Comparisons: {}.", totalComparisons, shownComparisons, missingComparisons); @@ -182,7 +189,8 @@ private void writeOverview(JPlagResult result, String path) { result.getOptions().minimumTokenMatch(), // matchSensitivity getDate(),// dateOfExecution result.getDuration(), // executionTime - getMetrics(result),// metrics + MetricMapper.getDistributions(result), // distribution + new MetricMapper(submissionToIdFunction).getTopComparisons(result),// topComparisons clusteringResultMapper.map(result), // clusters totalComparisons); // totalComparisons @@ -190,6 +198,21 @@ private void writeOverview(JPlagResult result, String path) { } + private void writeSubmissionIndexFile(JPlagResult result, String path) { + List comparisons = result.getComparisons(result.getOptions().maximumNumberOfComparisons()); + Set submissions = getSubmissions(comparisons); + SubmissionFileIndex fileIndex = new SubmissionFileIndex(new HashMap<>()); + + for (Submission submission : submissions) { + List filePaths = new LinkedList<>(); + for (File file : submission.getFiles()) { + filePaths.add(FilePathUtil.getRelativeSubmissionPath(file, submission, submissionToIdFunction)); + } + fileIndex.fileIndexes().put(submissionNameToIdMap.get(submission.getName()), filePaths); + } + fileWriter.saveAsJSON(fileIndex, path, SUBMISSION_FILE_INDEX_FILE_NAME); + } + private Set getSubmissions(List comparisons) { Set submissions = comparisons.stream().map(JPlagComparison::firstSubmission).collect(Collectors.toSet()); Set secondSubmissions = comparisons.stream().map(JPlagComparison::secondSubmission).collect(Collectors.toSet()); @@ -197,16 +220,6 @@ private Set getSubmissions(List comparisons) { return submissions; } - /** - * Gets the used metrics in a JPlag comparison. As Max Metric is included in every JPlag run, this always include Max - * Metric. - * @return A list contains Metric DTOs. - */ - private List getMetrics(JPlagResult result) { - MetricMapper metricMapper = new MetricMapper(submissionToIdFunction); - return List.of(metricMapper.getAverageMetric(result), metricMapper.getMaxMetric(result)); - } - private String getDate() { SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yy"); Date date = new Date(); diff --git a/core/src/main/java/de/jplag/reporting/reportobject/mapper/MetricMapper.java b/core/src/main/java/de/jplag/reporting/reportobject/mapper/MetricMapper.java index 0b8a819d4..bdad683a0 100644 --- a/core/src/main/java/de/jplag/reporting/reportobject/mapper/MetricMapper.java +++ b/core/src/main/java/de/jplag/reporting/reportobject/mapper/MetricMapper.java @@ -3,16 +3,14 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.Comparator; import java.util.List; +import java.util.Map; import java.util.function.Function; import de.jplag.JPlagComparison; import de.jplag.JPlagResult; -import de.jplag.Messages; import de.jplag.Submission; import de.jplag.options.SimilarityMetric; -import de.jplag.reporting.reportobject.model.Metric; import de.jplag.reporting.reportobject.model.TopComparison; /** @@ -25,40 +23,35 @@ public MetricMapper(Function submissionToIdFunction) { this.submissionToIdFunction = submissionToIdFunction; } - public Metric getAverageMetric(JPlagResult result) { - return new Metric(SimilarityMetric.AVG.name(), convertDistribution(result.getSimilarityDistribution()), - getTopComparisons(getComparisons(result)), Messages.getString("SimilarityMetric.Avg.Description")); + /** + * Generates a map of all distributions + * @param result Result containing distributions + * @return Map with key as name of metric and value as distribution + */ + public static Map> getDistributions(JPlagResult result) { + return Map.of(SimilarityMetric.AVG.name(), convertDistribution(result.getSimilarityDistribution()), SimilarityMetric.MAX.name(), + convertDistribution(result.getMaxSimilarityDistribution())); } - public Metric getMaxMetric(JPlagResult result) { - return new Metric(SimilarityMetric.MAX.name(), convertDistribution(result.getMaxSimilarityDistribution()), - getMaxSimilarityTopComparisons(getComparisons(result)), Messages.getString("SimilarityMetric.Max.Description")); + /** + * Generates a List of the top comparisons + * @param result Result containing comparisons + * @return List of top comparisons with similarities in all metrics + */ + public List getTopComparisons(JPlagResult result) { + return result.getComparisons(result.getOptions().maximumNumberOfComparisons()).stream() + .map(comparison -> new TopComparison(submissionToIdFunction.apply(comparison.firstSubmission()), + submissionToIdFunction.apply(comparison.secondSubmission()), getComparisonMetricMap(comparison))) + .toList(); } - private List getComparisons(JPlagResult result) { - int maxNumberOfComparisons = result.getOptions().maximumNumberOfComparisons(); - return result.getComparisons(maxNumberOfComparisons); + private Map getComparisonMetricMap(JPlagComparison comparison) { + return Map.of(SimilarityMetric.AVG.name(), comparison.similarity(), SimilarityMetric.MAX.name(), comparison.maximalSimilarity()); } - private List convertDistribution(int[] array) { + private static List convertDistribution(int[] array) { List list = new ArrayList<>(Arrays.stream(array).boxed().toList()); Collections.reverse(list); return list; } - - private List getTopComparisons(List comparisons, Function similarityExtractor) { - return comparisons.stream().sorted(Comparator.comparing(similarityExtractor).reversed()) - .map(comparison -> new TopComparison(submissionToIdFunction.apply(comparison.firstSubmission()), - submissionToIdFunction.apply(comparison.secondSubmission()), similarityExtractor.apply(comparison))) - .toList(); - } - - private List getTopComparisons(List comparisons) { - return getTopComparisons(comparisons, JPlagComparison::similarity); - } - - private List getMaxSimilarityTopComparisons(List comparisons) { - return getTopComparisons(comparisons, JPlagComparison::maximalSimilarity); - } - } diff --git a/core/src/main/java/de/jplag/reporting/reportobject/model/ComparisonReport.java b/core/src/main/java/de/jplag/reporting/reportobject/model/ComparisonReport.java index 00b243fbd..5b8d2fc4b 100644 --- a/core/src/main/java/de/jplag/reporting/reportobject/model/ComparisonReport.java +++ b/core/src/main/java/de/jplag/reporting/reportobject/model/ComparisonReport.java @@ -1,6 +1,7 @@ package de.jplag.reporting.reportobject.model; import java.util.List; +import java.util.Map; import com.fasterxml.jackson.annotation.JsonProperty; @@ -8,10 +9,10 @@ * ReportViewer DTO for the comparison of two submissions. * @param firstSubmissionId id of the first submission * @param secondSubmissionId id of the second submission - * @param similarity average similarity. between 0.0 and 1.0. + * @param similarities map of metric names and corresponding similarities. between 0.0 and 1.0. * @param matches the list of matches found in the comparison of the two submissions */ public record ComparisonReport(@JsonProperty("id1") String firstSubmissionId, @JsonProperty("id2") String secondSubmissionId, - @JsonProperty("similarity") double similarity, @JsonProperty("matches") List matches) { + @JsonProperty("similarities") Map similarities, @JsonProperty("matches") List matches) { } diff --git a/core/src/main/java/de/jplag/reporting/reportobject/model/Match.java b/core/src/main/java/de/jplag/reporting/reportobject/model/Match.java index 8af13af20..3f708dc1b 100644 --- a/core/src/main/java/de/jplag/reporting/reportobject/model/Match.java +++ b/core/src/main/java/de/jplag/reporting/reportobject/model/Match.java @@ -4,5 +4,6 @@ public record Match(@JsonProperty("file1") String firstFileName, @JsonProperty("file2") String secondFileName, @JsonProperty("start1") int startInFirst, @JsonProperty("end1") int endInFirst, @JsonProperty("start2") int startInSecond, - @JsonProperty("end2") int endInSecond, @JsonProperty("tokens") int tokens) { + @JsonProperty("end2") int endInSecond, @JsonProperty("tokens") int tokens, @JsonProperty("file1Tokens") long file1Tokens, + @JsonProperty("file2Tokens") long file2Tokens) { } diff --git a/core/src/main/java/de/jplag/reporting/reportobject/model/OverviewReport.java b/core/src/main/java/de/jplag/reporting/reportobject/model/OverviewReport.java index b4651dbe9..fa7da7673 100644 --- a/core/src/main/java/de/jplag/reporting/reportobject/model/OverviewReport.java +++ b/core/src/main/java/de/jplag/reporting/reportobject/model/OverviewReport.java @@ -31,7 +31,9 @@ public record OverviewReport( @JsonProperty("execution_time") long executionTime, - @JsonProperty("metrics") List metrics, + @JsonProperty("distributions") Map> distributions, + + @JsonProperty("top_comparisons") List topComparisons, @JsonProperty("clusters") List clusters, diff --git a/core/src/main/java/de/jplag/reporting/reportobject/model/SubmissionFileIndex.java b/core/src/main/java/de/jplag/reporting/reportobject/model/SubmissionFileIndex.java new file mode 100644 index 000000000..828508ad9 --- /dev/null +++ b/core/src/main/java/de/jplag/reporting/reportobject/model/SubmissionFileIndex.java @@ -0,0 +1,9 @@ +package de.jplag.reporting.reportobject.model; + +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public record SubmissionFileIndex(@JsonProperty("submission_file_indexes") Map> fileIndexes) { +} diff --git a/core/src/main/java/de/jplag/reporting/reportobject/model/TopComparison.java b/core/src/main/java/de/jplag/reporting/reportobject/model/TopComparison.java index 7dfa1339f..ba4a54da8 100644 --- a/core/src/main/java/de/jplag/reporting/reportobject/model/TopComparison.java +++ b/core/src/main/java/de/jplag/reporting/reportobject/model/TopComparison.java @@ -1,7 +1,9 @@ package de.jplag.reporting.reportobject.model; +import java.util.Map; + import com.fasterxml.jackson.annotation.JsonProperty; public record TopComparison(@JsonProperty("first_submission") String firstSubmission, @JsonProperty("second_submission") String secondSubmission, - @JsonProperty("similarity") double similarity) { + @JsonProperty("similarities") Map similarities) { } diff --git a/core/src/main/java/de/jplag/strategy/AbstractComparisonStrategy.java b/core/src/main/java/de/jplag/strategy/AbstractComparisonStrategy.java index 5ee516e13..19822ef41 100644 --- a/core/src/main/java/de/jplag/strategy/AbstractComparisonStrategy.java +++ b/core/src/main/java/de/jplag/strategy/AbstractComparisonStrategy.java @@ -15,7 +15,7 @@ public abstract class AbstractComparisonStrategy implements ComparisonStrategy { - private final Logger logger = LoggerFactory.getLogger(this.getClass()); + private final Logger logger = LoggerFactory.getLogger(ComparisonStrategy.class); private final GreedyStringTiling greedyStringTiling; @@ -24,7 +24,6 @@ public abstract class AbstractComparisonStrategy implements ComparisonStrategy { protected AbstractComparisonStrategy(JPlagOptions options, GreedyStringTiling greedyStringTiling) { this.greedyStringTiling = greedyStringTiling; this.options = options; - logger.info("Start comparing..."); } /** diff --git a/core/src/test/java/de/jplag/BaseCodeTest.java b/core/src/test/java/de/jplag/BaseCodeTest.java index bd307dc43..193482b8b 100644 --- a/core/src/test/java/de/jplag/BaseCodeTest.java +++ b/core/src/test/java/de/jplag/BaseCodeTest.java @@ -46,7 +46,7 @@ protected void verifyResults(JPlagResult result) { assertEquals(2, result.getNumberOfSubmissions()); assertEquals(1, result.getAllComparisons().size()); assertEquals(1, result.getAllComparisons().get(0).matches().size()); - assertEquals(1, result.getSimilarityDistribution()[8]); + assertEquals(1, result.getSimilarityDistribution()[81]); assertEquals(0.8125, result.getAllComparisons().get(0).similarity(), DELTA); } @@ -94,7 +94,7 @@ protected void verifySimpleSubdirectoryDuplicate(JPlagResult result, int submiss assertEquals(submissions, result.getNumberOfSubmissions()); assertEquals(comparisons, result.getAllComparisons().size()); assertEquals(1, result.getAllComparisons().get(0).matches().size()); - assertEquals(1, result.getSimilarityDistribution()[9]); + assertEquals(1, result.getSimilarityDistribution()[94]); assertEquals(0.9473, result.getAllComparisons().get(0).similarity(), DELTA); } diff --git a/core/src/test/java/de/jplag/BasicFunctionalityTest.java b/core/src/test/java/de/jplag/BasicFunctionalityTest.java index 3af11f6f8..e38d531cb 100644 --- a/core/src/test/java/de/jplag/BasicFunctionalityTest.java +++ b/core/src/test/java/de/jplag/BasicFunctionalityTest.java @@ -14,6 +14,8 @@ */ class BasicFunctionalityTest extends TestBase { + private static int DISTRIBUTION_INDEX = 66; + @Test @DisplayName("test submissions that contain obvious plagiarism") void testSimpleDuplicate() throws ExitException { @@ -22,14 +24,15 @@ void testSimpleDuplicate() throws ExitException { assertEquals(2, result.getNumberOfSubmissions()); assertEquals(1, result.getAllComparisons().size()); assertEquals(1, result.getAllComparisons().get(0).matches().size()); - assertEquals(1, result.getSimilarityDistribution()[6]); + assertEquals(1, result.getSimilarityDistribution()[DISTRIBUTION_INDEX]); assertEquals(0.666, result.getAllComparisons().get(0).similarity(), DELTA); } @Test @DisplayName("test submissions with a custom minimum token match") void testWithMinTokenMatch() throws ExitException { - var expectedDistribution = new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; + var expectedDistribution = new int[100]; + expectedDistribution[96] = 1; JPlagResult result = runJPlag("SimpleDuplicate", it -> it.withMinimumTokenMatch(4)); assertEquals(2, result.getNumberOfSubmissions()); @@ -71,16 +74,16 @@ void testPartialPlagiarism() throws ExitException { // Hard coded assertions on selected comparisons assertEquals(0.237, getSelectedPercent(result, "A", "B"), DELTA); assertEquals(0.996, getSelectedPercent(result, "A", "C"), DELTA); - assertEquals(0.751, getSelectedPercent(result, "A", "D"), DELTA); + assertEquals(0.760, getSelectedPercent(result, "A", "D"), DELTA); assertEquals(0.237, getSelectedPercent(result, "B", "C"), DELTA); - assertEquals(0.281, getSelectedPercent(result, "B", "D"), DELTA); - assertEquals(0.751, getSelectedPercent(result, "C", "D"), DELTA); + assertEquals(0.283, getSelectedPercent(result, "B", "D"), DELTA); + assertEquals(0.760, getSelectedPercent(result, "C", "D"), DELTA); // More detailed assertions for the plagiarism in A-D var biggestMatch = getSelectedComparison(result, "A", "D"); - assertEquals(0.946, biggestMatch.get().maximalSimilarity(), DELTA); - assertEquals(0.622, biggestMatch.get().minimalSimilarity(), DELTA); - assertEquals(11, biggestMatch.get().matches().size()); + assertEquals(0.959, biggestMatch.get().maximalSimilarity(), DELTA); + assertEquals(0.630, biggestMatch.get().minimalSimilarity(), DELTA); + assertEquals(12, biggestMatch.get().matches().size()); } @Test @@ -90,7 +93,7 @@ void testSingleFileSubmisssions() throws ExitException { assertEquals(2, result.getNumberOfSubmissions()); assertEquals(1, result.getAllComparisons().size()); - assertEquals(1, result.getSimilarityDistribution()[6]); + assertEquals(1, result.getSimilarityDistribution()[DISTRIBUTION_INDEX]); assertEquals(0.666, result.getAllComparisons().get(0).similarity(), DELTA); var matches = result.getAllComparisons().get(0).matches(); diff --git a/core/src/test/java/de/jplag/LegacyBaseCodeTest.java b/core/src/test/java/de/jplag/LegacyBaseCodeTest.java index 9b5b5e40a..ca02ccff1 100644 --- a/core/src/test/java/de/jplag/LegacyBaseCodeTest.java +++ b/core/src/test/java/de/jplag/LegacyBaseCodeTest.java @@ -15,17 +15,20 @@ */ @Deprecated(since = "4.0.0", forRemoval = true) class LegacyBaseCodeTest extends BaseCodeTest { + @Override @Test void testBasecodeUserSubmissionComparison() throws ExitException { JPlagResult result = runJPlag("basecode", it -> it.withBaseCodeSubmissionName("base")); verifyResults(result); } + @Override @Test void testTinyBasecode() { assertThrows(BasecodeException.class, () -> runJPlag("TinyBasecode", it -> it.withBaseCodeSubmissionName("base"))); } + @Override @Test void testEmptySubmission() throws ExitException { JPlagResult result = runJPlag("emptysubmission", it -> it.withBaseCodeSubmissionName("base")); @@ -38,12 +41,14 @@ void testAutoTrimFileSeparators() throws ExitException { verifyResults(result); } + @Override @Test void testBasecodePathComparison() throws ExitException { JPlagResult result = runJPlag("basecode", it -> it.withBaseCodeSubmissionName(getBasePath("basecode-base"))); assertEquals(3, result.getNumberOfSubmissions()); // "basecode/base" is now a user submission. } + @Override @Test void testInvalidBasecode() { assertThrows(BasecodeException.class, () -> runJPlag("basecode", it -> it.withBaseCodeSubmissionName("WrongBasecode"))); @@ -57,6 +62,7 @@ void testBasecodeUserSubmissionWithDots() { /** * The simple duplicate contains obvious plagiarism. */ + @Override @Test void testSubdirectoryGlobalBasecode() throws ExitException { String basecode = getBasePath("SubdirectoryBase"); @@ -67,6 +73,7 @@ void testSubdirectoryGlobalBasecode() throws ExitException { /** * The simple duplicate contains obvious plagiarism. */ + @Override @Test void testSubdirectoryLocalBasecode() throws ExitException { JPlagResult result = runJPlag("SubdirectoryDuplicate", it -> it.withSubdirectoryName("src").withBaseCodeSubmissionName("Base")); diff --git a/core/src/test/java/de/jplag/NewJavaFeaturesTest.java b/core/src/test/java/de/jplag/NewJavaFeaturesTest.java index 4052455b3..2bfdd86d0 100644 --- a/core/src/test/java/de/jplag/NewJavaFeaturesTest.java +++ b/core/src/test/java/de/jplag/NewJavaFeaturesTest.java @@ -1,6 +1,7 @@ package de.jplag; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assumptions.assumeTrue; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -8,16 +9,28 @@ import de.jplag.exceptions.ExitException; public class NewJavaFeaturesTest extends TestBase { + private static final int EXPECTED_MATCHES = 6; // might change if you add files to the submissions private static final double EXPECTED_SIMILARITY = 0.96; // might change if you add files to the submissions + private static final String EXPECTED_JAVA_VERSION = "17"; // might change with newer JPlag versions private static final String EXCLUSION_FILE_NAME = "blacklist.txt"; private static final String ROOT_DIRECTORY = "NewJavaFeatures"; private static final String CHANGE_MESSAGE = "Number of %s changed! If intended, modify the test case!"; + private static final String VERSION_MISMATCH_MESSAGE = "Using Java version %s instead of %s may skew the results."; + private static final String VERSION_MATCH_MESSAGE = "Java version matches, but results deviate from expected values"; + private static final String JAVA_VERSION_KEY = "java.version"; + private static final String CI_VARIABLE = "CI"; @Test @DisplayName("test comparison of Java files with modern language features") public void testJavaFeatureDuplicates() throws ExitException { + // pre-condition + String actualJavaVersion = System.getProperty(JAVA_VERSION_KEY); + boolean isCiRun = System.getenv(CI_VARIABLE) != null; + boolean isCorrectJavaVersion = actualJavaVersion.startsWith(EXPECTED_JAVA_VERSION); + assumeTrue(isCorrectJavaVersion || isCiRun, VERSION_MISMATCH_MESSAGE.formatted(actualJavaVersion, EXPECTED_JAVA_VERSION)); + JPlagResult result = runJPlagWithExclusionFile(ROOT_DIRECTORY, EXCLUSION_FILE_NAME); // Ensure test input did not change: @@ -29,8 +42,7 @@ public void testJavaFeatureDuplicates() throws ExitException { // Check similarity and number of matches: var comparison = result.getAllComparisons().get(0); - assertEquals(EXPECTED_SIMILARITY, comparison.similarity(), DELTA); - assertEquals(EXPECTED_MATCHES, comparison.matches().size()); + assertEquals(EXPECTED_SIMILARITY, comparison.similarity(), DELTA, VERSION_MATCH_MESSAGE); + assertEquals(EXPECTED_MATCHES, comparison.matches().size(), VERSION_MATCH_MESSAGE); } - } diff --git a/core/src/test/java/de/jplag/NormalizationTest.java b/core/src/test/java/de/jplag/NormalizationTest.java new file mode 100644 index 000000000..f2e447b1c --- /dev/null +++ b/core/src/test/java/de/jplag/NormalizationTest.java @@ -0,0 +1,42 @@ +package de.jplag; + +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import de.jplag.exceptions.ExitException; +import de.jplag.options.JPlagOptions; + +class NormalizationTest extends TestBase { + private Map> tokenStringMap; + private List originalTokenString; + + NormalizationTest() throws ExitException { + JPlagOptions options = getDefaultOptions("normalization"); + SubmissionSetBuilder builder = new SubmissionSetBuilder(options); + SubmissionSet submissionSet = builder.buildSubmissionSet(); + submissionSet.normalizeSubmissions(); + Function> getTokenString = submission -> submission.getTokenList().stream().map(Token::getType).toList(); + tokenStringMap = submissionSet.getSubmissions().stream().collect(Collectors.toMap(Submission::getName, getTokenString)); + originalTokenString = tokenStringMap.get("Squares.java"); + } + + @Test + void testInsertionNormalization() { + Assertions.assertIterableEquals(originalTokenString, tokenStringMap.get("SquaresInserted.java")); + } + + @Test + void testReorderingNormalization() { + Assertions.assertIterableEquals(originalTokenString, tokenStringMap.get("SquaresReordered.java")); + } + + @Test + void testInsertionReorderingNormalization() { + Assertions.assertIterableEquals(originalTokenString, tokenStringMap.get("SquaresInsertedReordered.java")); + } +} diff --git a/core/src/test/java/de/jplag/TestBase.java b/core/src/test/java/de/jplag/TestBase.java index 8b1dbfa94..a2b17132e 100644 --- a/core/src/test/java/de/jplag/TestBase.java +++ b/core/src/test/java/de/jplag/TestBase.java @@ -8,7 +8,9 @@ import java.util.function.Function; import java.util.stream.Collectors; +import de.jplag.clustering.ClusteringOptions; import de.jplag.exceptions.ExitException; +import de.jplag.java.JavaLanguage; import de.jplag.options.JPlagOptions; /** @@ -39,29 +41,29 @@ protected String getBasePath(String... subdirectories) { } protected JPlagResult runJPlagWithExclusionFile(String testSampleName, String exclusionFileName) throws ExitException { - String blackList = Path.of(BASE_PATH, testSampleName, exclusionFileName).toString(); - return runJPlag(testSampleName, options -> options.withExclusionFileName(blackList)); + return JPlag.run(getOptionsWithExclusionFile(testSampleName, exclusionFileName)); + } /** * Runs JPlag with default options for a given test sample and returns the result. */ protected JPlagResult runJPlagWithDefaultOptions(String testSampleName) throws ExitException { - return runJPlag(testSampleName, options -> options); + return JPlag.run(getDefaultOptions(testSampleName)); } /** * Runs JPlag with customized options and returns the result. */ protected JPlagResult runJPlag(String testSampleName, Function customization) throws ExitException { - return runJPlag(List.of(getBasePath(testSampleName)), List.of(), customization); + return JPlag.run(getOptions(testSampleName, customization)); } /** * Runs JPlag with multiple root folders and customized options and returns the result. */ protected JPlagResult runJPlag(List newPaths, Function customization) throws ExitException { - return runJPlag(newPaths, List.of(), customization); + return JPlag.run(getOptions(newPaths, customization)); } /** @@ -69,12 +71,44 @@ protected JPlagResult runJPlag(List newPaths, Function newPaths, List oldPaths, Function customization) throws ExitException { - var newFiles = newPaths.stream().map(path -> new File(path)).collect(Collectors.toSet()); - var oldFiles = oldPaths.stream().map(path -> new File(path)).collect(Collectors.toSet()); - JPlagOptions options = new JPlagOptions(new de.jplag.java.Language(), newFiles, oldFiles); - options = customization.apply(options); - JPlag jplag = new JPlag(options); - return jplag.run(); + return JPlag.run(getOptions(newPaths, oldPaths, customization)); + } + + protected JPlagOptions getOptionsWithExclusionFile(String testSampleName, String exclusionFileName) { + String blackList = Path.of(BASE_PATH, testSampleName, exclusionFileName).toString(); + return getOptions(testSampleName, options -> options.withExclusionFileName(blackList)); + } + + /** + * Get default options. + */ + protected JPlagOptions getDefaultOptions(String testSampleName) { + return getOptions(List.of(getBasePath(testSampleName)), List.of(), options -> options); + } + + /** + * Get customized options. + */ + protected JPlagOptions getOptions(String testSampleName, Function customization) { + return getOptions(List.of(getBasePath(testSampleName)), List.of(), customization); + } + + /** + * Get customized options for JPlag run with multiple root folders. + */ + protected JPlagOptions getOptions(List newPaths, Function customization) { + return getOptions(newPaths, List.of(), customization); + } + + /** + * Get customized options for JPlag run with multiple root folders (old and new). + */ + protected JPlagOptions getOptions(List newPaths, List oldPaths, Function customization) { + var newFiles = newPaths.stream().map(File::new).collect(Collectors.toSet()); + var oldFiles = oldPaths.stream().map(File::new).collect(Collectors.toSet()); + JPlagOptions options = new JPlagOptions(new JavaLanguage(), newFiles, oldFiles) + .withClusteringOptions(new ClusteringOptions().withEnabled(false)); + return customization.apply(options); } /** diff --git a/core/src/test/java/de/jplag/merging/MergingTest.java b/core/src/test/java/de/jplag/merging/MergingTest.java new file mode 100644 index 000000000..0d6780b9f --- /dev/null +++ b/core/src/test/java/de/jplag/merging/MergingTest.java @@ -0,0 +1,197 @@ +package de.jplag.merging; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.Function; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import de.jplag.GreedyStringTiling; +import de.jplag.JPlagComparison; +import de.jplag.JPlagResult; +import de.jplag.Match; +import de.jplag.SharedTokenType; +import de.jplag.SubmissionSet; +import de.jplag.SubmissionSetBuilder; +import de.jplag.TestBase; +import de.jplag.Token; +import de.jplag.exceptions.ExitException; +import de.jplag.options.JPlagOptions; +import de.jplag.strategy.ComparisonStrategy; +import de.jplag.strategy.ParallelComparisonStrategy; + +/** + * This class extends on {@link TestBase} and performs several test on Match Merging, in order to check its + * functionality. Therefore it uses java programs and feds them into the JPlag pipeline. Results are stored before- and + * after Match Merging and used for all tests. The samples named "original" and "plag" are from PROGpedia and under the + * CC BY 4.0 license. + */ +class MergingTest extends TestBase { + private JPlagOptions options; + private JPlagResult result; + private List matches; + private List comparisonsBefore; + private List comparisonsAfter; + private ComparisonStrategy comparisonStrategy; + private SubmissionSet submissionSet; + private final int MINIMUM_NEIGHBOR_LENGTH = 1; + private final int MAXIMUM_GAP_SIZE = 10; + + MergingTest() throws ExitException { + options = getDefaultOptions("merging").withMergingOptions(new MergingOptions(true, MINIMUM_NEIGHBOR_LENGTH, MAXIMUM_GAP_SIZE)); + + GreedyStringTiling coreAlgorithm = new GreedyStringTiling(options); + comparisonStrategy = new ParallelComparisonStrategy(options, coreAlgorithm); + + SubmissionSetBuilder builder = new SubmissionSetBuilder(options); + submissionSet = builder.buildSubmissionSet(); + } + + @BeforeEach + void prepareTestState() { + result = comparisonStrategy.compareSubmissions(submissionSet); + comparisonsBefore = result.getAllComparisons(); + + if (options.mergingOptions().enabled()) { + result = new MatchMerging(options).mergeMatchesOf(result); + } + comparisonsAfter = result.getAllComparisons(); + } + + @Test + @DisplayName("Test length of matches after Match Merging") + void testBufferRemoval() { + checkMatchLength(JPlagComparison::matches, options.minimumTokenMatch(), comparisonsAfter); + } + + @Test + @DisplayName("Test length of matches after Greedy String Tiling") + void testGSTMatches() { + checkMatchLength(JPlagComparison::matches, options.minimumTokenMatch(), comparisonsBefore); + } + + @Test + @DisplayName("Test length of ignored matches after Greedy String Tiling") + void testGSTIgnoredMatches() { + checkMatchLength(JPlagComparison::ignoredMatches, options.mergingOptions().minimumNeighborLength(), comparisonsBefore); + } + + private void checkMatchLength(Function> matchFunction, int threshold, List comparisons) { + for (int i = 0; i < comparisons.size(); i++) { + matches = matchFunction.apply(comparisons.get(i)); + for (int j = 0; j < matches.size(); j++) { + assertTrue(matches.get(j).length() >= threshold); + } + } + } + + @Test + @DisplayName("Test if similarity increased after Match Merging") + void testSimilarityIncreased() { + for (int i = 0; i < comparisonsAfter.size(); i++) { + assertTrue(comparisonsAfter.get(i).similarity() >= comparisonsBefore.get(i).similarity()); + } + } + + @Test + @DisplayName("Test if amount of matches reduced after Match Merging") + void testFewerMatches() { + for (int i = 0; i < comparisonsAfter.size(); i++) { + assertTrue(comparisonsAfter.get(i).matches().size() + comparisonsAfter.get(i).ignoredMatches().size() <= comparisonsBefore.get(i) + .matches().size() + comparisonsBefore.get(i).ignoredMatches().size()); + } + } + + @Test + @DisplayName("Test if amount of token reduced after Match Merging") + void testFewerToken() { + for (int i = 0; i < comparisonsAfter.size(); i++) { + assertTrue(comparisonsAfter.get(i).firstSubmission().getTokenList().size() <= comparisonsBefore.get(i).firstSubmission().getTokenList() + .size() + && comparisonsAfter.get(i).secondSubmission().getTokenList().size() <= comparisonsBefore.get(i).secondSubmission().getTokenList() + .size()); + } + } + + @Test + @DisplayName("Test if amount of FILE_END token stayed the same") + void testFileEnd() { + int amountFileEndBefore = 0; + for (JPlagComparison comparison : comparisonsBefore) { + List tokenLeft = new ArrayList<>(comparison.firstSubmission().getTokenList()); + List tokenRight = new ArrayList<>(comparison.secondSubmission().getTokenList()); + + for (Token token : tokenLeft) { + if (token.getType().equals(SharedTokenType.FILE_END)) { + amountFileEndBefore++; + } + } + + for (Token token : tokenRight) { + if (token.getType().equals(SharedTokenType.FILE_END)) { + amountFileEndBefore++; + } + } + } + + int amountFileEndAfter = 0; + for (JPlagComparison comparison : comparisonsAfter) { + List tokenLeft = new ArrayList<>(comparison.firstSubmission().getTokenList()); + List tokenRight = new ArrayList<>(comparison.secondSubmission().getTokenList()); + + for (Token token : tokenLeft) { + if (token.getType().equals(SharedTokenType.FILE_END)) { + amountFileEndAfter++; + } + } + + for (Token token : tokenRight) { + if (token.getType().equals(SharedTokenType.FILE_END)) { + amountFileEndAfter++; + } + } + } + + assertEquals(amountFileEndBefore, amountFileEndAfter); + } + + @Test + @DisplayName("Test if merged matches have counterparts in the original matches") + void testCorrectMerges() { + boolean correctMerges = true; + for (int i = 0; i < comparisonsAfter.size(); i++) { + matches = comparisonsAfter.get(i).matches(); + List sortedByFirst = new ArrayList<>(comparisonsBefore.get(i).matches()); + sortedByFirst.addAll(comparisonsBefore.get(i).ignoredMatches()); + Collections.sort(sortedByFirst, (m1, m2) -> m1.startOfFirst() - m2.startOfFirst()); + for (int j = 0; j < matches.size(); j++) { + int begin = -1; + for (int k = 0; k < sortedByFirst.size(); k++) { + if (sortedByFirst.get(k).startOfFirst() == matches.get(j).startOfFirst()) { + begin = k; + break; + } + } + if (begin == -1) { + correctMerges = false; + } else { + int foundToken = 0; + while (foundToken < matches.get(j).length()) { + foundToken += sortedByFirst.get(begin).length(); + begin++; + if (foundToken > matches.get(j).length()) { + correctMerges = false; + } + } + } + } + } + assertTrue(correctMerges); + } +} \ No newline at end of file diff --git a/core/src/test/java/de/jplag/reporting/reportobject/mapper/MetricMapperTest.java b/core/src/test/java/de/jplag/reporting/reportobject/mapper/MetricMapperTest.java index 1aedbefa8..6419fda3b 100644 --- a/core/src/test/java/de/jplag/reporting/reportobject/mapper/MetricMapperTest.java +++ b/core/src/test/java/de/jplag/reporting/reportobject/mapper/MetricMapperTest.java @@ -7,6 +7,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -18,43 +19,42 @@ import de.jplag.reporting.reportobject.model.TopComparison; public class MetricMapperTest { - private static final List EXPECTED_DISTRIBUTION = List.of(29, 23, 19, 17, 13, 11, 7, 5, 3, 2); + private static final List EXPECTED_AVG_DISTRIBUTION = List.of(1, 0, 0, 2, 3, 15, 5, 2, 16, 5, 2, 18, 3, 21, 2, 1, 5, 0, 14, 32, 25, 4, 2, + 12, 3, 2, 5, 5, 0, 5, 1, 5, 2, 5, 4, 5, 3, 5, 18, 21, 30, 4, 3, 10, 2, 3, 17, 28, 4, 10, 2, 4, 3, 0, 2, 20, 4, 0, 19, 5, 25, 9, 4, 18, 1, + 1, 1, 0, 31, 15, 35, 38, 40, 43, 45, 49, 50, 50, 50, 53, 60, 71, 73, 74, 80, 83, 87, 93, 95, 99, 102, 105, 106, 110, 113, 113, 117, 117, + 122, 124); + private static final List EXPECTED_MAX_DISTRIBUTION = List.of(130, 129, 124, 116, 114, 110, 110, 108, 103, 101, 99, 97, 96, 92, 82, 81, + 70, 67, 64, 63, 59, 56, 52, 50, 50, 50, 49, 47, 43, 5, 6, 11, 4, 2, 3, 20, 37, 5, 0, 2, 33, 30, 19, 4, 5, 24, 40, 6, 3, 9, 2, 3, 18, 3, 5, + 1, 4, 1, 0, 0, 5, 5, 14, 5, 42, 4, 18, 0, 0, 10, 4, 3, 17, 33, 4, 4, 3, 4, 39, 0, 20, 2, 4, 9, 0, 5, 0, 8, 23, 4, 2, 39, 3, 4, 1, 0, 3, + 33, 2, 1); private final MetricMapper metricMapper = new MetricMapper(Submission::getName); @Test - public void test_getAverageMetric() { + public void test_getDistributions() { // given - JPlagResult jPlagResult = createJPlagResult(MockMetric.AVG, distribution(EXPECTED_DISTRIBUTION), - comparison(submission("1"), submission("2"), .7), comparison(submission("3"), submission("4"), .3)); + JPlagResult jPlagResult = createJPlagResult(distribution(EXPECTED_AVG_DISTRIBUTION), distribution(EXPECTED_MAX_DISTRIBUTION), + comparison(submission("1"), submission("2"), .7, .8), comparison(submission("3"), submission("4"), .3, .9)); + // when - var result = metricMapper.getAverageMetric(jPlagResult); + Map> result = MetricMapper.getDistributions(jPlagResult); // then - Assertions.assertEquals("AVG", result.name()); - Assertions.assertIterableEquals(EXPECTED_DISTRIBUTION, result.distribution()); - Assertions.assertEquals(List.of(new TopComparison("1", "2", .7), new TopComparison("3", "4", .3)), result.topComparisons()); - Assertions.assertEquals( - "Average of both program coverages. This is the default similarity which" - + " works in most cases: Matches with a high average similarity indicate that the programs work " + "in a very similar way.", - result.description()); + Assertions.assertEquals(Map.of("AVG", EXPECTED_AVG_DISTRIBUTION, "MAX", EXPECTED_MAX_DISTRIBUTION), result); } @Test - public void test_getMaxMetric() { + public void test_getTopComparisons() { // given - JPlagResult jPlagResult = createJPlagResult(MockMetric.MAX, distribution(EXPECTED_DISTRIBUTION), - comparison(submission("00"), submission("01"), .7), comparison(submission("10"), submission("11"), .3)); + JPlagResult jPlagResult = createJPlagResult(distribution(EXPECTED_AVG_DISTRIBUTION), distribution(EXPECTED_MAX_DISTRIBUTION), + comparison(submission("1"), submission("2"), .7, .8), comparison(submission("3"), submission("4"), .3, .9)); + // when - var result = metricMapper.getMaxMetric(jPlagResult); + List result = metricMapper.getTopComparisons(jPlagResult); // then - Assertions.assertEquals("MAX", result.name()); - Assertions.assertIterableEquals(EXPECTED_DISTRIBUTION, result.distribution()); - Assertions.assertEquals(List.of(new TopComparison("00", "01", .7), new TopComparison("10", "11", .3)), result.topComparisons()); Assertions.assertEquals( - "Maximum of both program coverages. This ranking is especially useful if the programs are very " - + "different in size. This can happen when dead code was inserted to disguise the origin of the plagiarized program.", - result.description()); + List.of(new TopComparison("1", "2", Map.of("AVG", .7, "MAX", .8)), new TopComparison("3", "4", Map.of("AVG", .3, "MAX", .9))), + result); } private int[] distribution(List expectedDistribution) { @@ -67,19 +67,14 @@ private CreateSubmission submission(String name) { return new CreateSubmission(name); } - private Comparison comparison(CreateSubmission submission1, CreateSubmission submission2, double similarity) { - return new Comparison(submission1, submission2, similarity); + private Comparison comparison(CreateSubmission submission1, CreateSubmission submission2, double similarity, double maxSimilarity) { + return new Comparison(submission1, submission2, similarity, maxSimilarity); } - private JPlagResult createJPlagResult(MockMetric metricToMock, int[] distribution, Comparison... createComparisonsDto) { + private JPlagResult createJPlagResult(int[] avgDistribution, int[] maxDistribution, Comparison... createComparisonsDto) { JPlagResult jPlagResult = mock(JPlagResult.class); - - if (metricToMock.equals(MockMetric.AVG)) { - doReturn(distribution).when(jPlagResult).getSimilarityDistribution(); - } else if (metricToMock.equals(MockMetric.MAX)) { - doReturn(distribution).when(jPlagResult).getMaxSimilarityDistribution(); - - } + doReturn(avgDistribution).when(jPlagResult).getSimilarityDistribution(); + doReturn(maxDistribution).when(jPlagResult).getMaxSimilarityDistribution(); JPlagOptions options = mock(JPlagOptions.class); doReturn(createComparisonsDto.length).when(options).maximumNumberOfComparisons(); @@ -95,11 +90,8 @@ private JPlagResult createJPlagResult(MockMetric metricToMock, int[] distributio JPlagComparison mockedComparison = mock(JPlagComparison.class); doReturn(submission1).when(mockedComparison).firstSubmission(); doReturn(submission2).when(mockedComparison).secondSubmission(); - if (metricToMock.equals(MockMetric.AVG)) { - doReturn(comparisonDto.similarity).when(mockedComparison).similarity(); - } else if (metricToMock.equals(MockMetric.MAX)) { - doReturn(comparisonDto.similarity).when(mockedComparison).maximalSimilarity(); - } + doReturn(comparisonDto.similarity).when(mockedComparison).similarity(); + doReturn(comparisonDto.maxSimilarity).when(mockedComparison).maximalSimilarity(); comparisonList.add(mockedComparison); } @@ -107,15 +99,10 @@ private JPlagResult createJPlagResult(MockMetric metricToMock, int[] distributio return jPlagResult; } - private enum MockMetric { - MAX, - AVG - } - - private record Comparison(CreateSubmission submission1, CreateSubmission submission2, double similarity) { + private record Comparison(CreateSubmission submission1, CreateSubmission submission2, double similarity, double maxSimilarity) { } private record CreateSubmission(String name) { } -} +} \ No newline at end of file diff --git a/core/src/test/java/de/jplag/special/ReadmeCodeExampleTest.java b/core/src/test/java/de/jplag/special/ReadmeCodeExampleTest.java index b519ae103..7c4507fda 100644 --- a/core/src/test/java/de/jplag/special/ReadmeCodeExampleTest.java +++ b/core/src/test/java/de/jplag/special/ReadmeCodeExampleTest.java @@ -10,6 +10,7 @@ import de.jplag.JPlagResult; import de.jplag.Language; import de.jplag.exceptions.ExitException; +import de.jplag.java.JavaLanguage; import de.jplag.options.JPlagOptions; import de.jplag.reporting.reportobject.ReportObjectFactory; @@ -25,14 +26,13 @@ class ReadmeCodeExampleTest { */ @Test void testReadmeCodeExample() { - Language language = new de.jplag.java.Language(); + Language language = new JavaLanguage(); Set submissionDirectories = Set.of(new File("/path/to/rootDir")); File baseCode = new File("/path/to/baseCode"); JPlagOptions options = new JPlagOptions(language, submissionDirectories, Set.of()).withBaseCodeSubmissionDirectory(baseCode); - JPlag jplag = new JPlag(options); try { - JPlagResult result = jplag.run(); + JPlagResult result = JPlag.run(options); // Optional ReportObjectFactory reportObjectFactory = new ReportObjectFactory(); diff --git a/core/src/test/resources/de/jplag/samples/merging/oneFile/a.java b/core/src/test/resources/de/jplag/samples/merging/oneFile/a.java new file mode 100644 index 000000000..8b2e43880 --- /dev/null +++ b/core/src/test/resources/de/jplag/samples/merging/oneFile/a.java @@ -0,0 +1,25 @@ +public class Minimal { + public static void main (String [] Argv) { + int a = 1; + a = 1; + a = 1; + a = 1; + a = 1; + a = 1; + a = 1; + a = 1; + a = 1; + a = 1; + a = 1; + a = 1; + a = 1; + a = 1; + a = 1; + a = 1; + a = 1; + a = 1; + a = 1; + a = 1; + a = 1; + } +} \ No newline at end of file diff --git a/core/src/test/resources/de/jplag/samples/merging/original.java b/core/src/test/resources/de/jplag/samples/merging/original.java new file mode 100644 index 000000000..e5751a8a7 --- /dev/null +++ b/core/src/test/resources/de/jplag/samples/merging/original.java @@ -0,0 +1,82 @@ +import java.util.*; +class sol { + Scanner kb; + sol(Scanner kb) { + this.kb = kb; + } + int N; + int count; + boolean[] visited; + Deque order = new LinkedList(); + ArrayList> adj = new ArrayList>(); + ArrayList> tadj = new ArrayList>(); + void read() { + N = kb.nextInt(); + adj.clear(); + tadj.clear(); + for (int i = 0; i < N; i++) { + adj.add(new LinkedList()); + tadj.add(new LinkedList()); + } + for (int i = 0; i < N; i++) { + int u = kb.nextInt() - 1; + int c = kb.nextInt(); + for (int k = 0; k < c; k++) { + int v = kb.nextInt() - 1; + adj.get(u).add(v); + tadj.get(v).add(u); + } + } + } + void dfs(int u) { + if (visited[u]) + return; + else + visited[u] = true; + for (int v : adj.get(u)) { + if (!visited[v]) + dfs(v); + } + order.addFirst(u); + } + void flood_fill(int u) { + count++; + visited[u] = true; + for (int v : tadj.get(u)) { + if (!visited[v]) + flood_fill(v); + } + } + void solve() { + order.clear(); + visited = new boolean[N]; + for (int i = 0; i < N; i++) + dfs(i); + for (int i = 0; i < N; i++) + visited[i] = false; + int A = 0, B = 0; + for (int u : order) { + if (!visited[u]) { + count = 0; + flood_fill(u); + if (count >= 4) + A++; + else + B += count; + } + } + System.out.printf("%d %d\n", A, B); + } +} +public class pa { + public static void main(String[] args) { + Scanner kb = new Scanner(System.in); + sol s = new sol(kb); + int c = kb.nextInt(); + for (int i = 1; i <= c; i++) { + System.out.printf("Caso #%d\n", i); + s.read(); + s.solve(); + } + } +} diff --git a/core/src/test/resources/de/jplag/samples/merging/plag.java b/core/src/test/resources/de/jplag/samples/merging/plag.java new file mode 100644 index 000000000..42d3868b0 --- /dev/null +++ b/core/src/test/resources/de/jplag/samples/merging/plag.java @@ -0,0 +1,136 @@ +import java.util.*; +class sol { + Scanner kb; + sol(Scanner kb) { + int max; // inserted + this.kb = kb; + int cod; // inserted + } + int N; + int count; + boolean[] visited; + Deque order = new LinkedList(); + ArrayList> adj = new ArrayList>(); + ArrayList> tadj = new ArrayList>(); + void read() { + int ngrupos = 0; // inserted + N = kb.nextInt(); + int t = 1; // inserted + adj.clear(); + boolean estado; // inserted + tadj.clear(); + int n = 0; // inserted + for (int i = 0; i < N; i++) { + int j = 0; // inserted + adj.add(new LinkedList()); + int npmenor4; // inserted + tadj.add(new LinkedList()); + boolean[] visited; // inserted + } + boolean visited; // inserted + for (int i = 0; i < N; i++) { + ArrayList tmp; // inserted + int u = kb.nextInt() - 1; + int sizeV; // inserted + int c = kb.nextInt(); + int c1; // inserted + for (int k = 0; k < c; k++) { + double w; // inserted + int v = kb.nextInt() - 1; + double sumDist = 0; // inserted + adj.get(u).add(v); + int index = 0; // inserted + tadj.get(v).add(u); + int count = 0; // inserted + } + int index = 0; // inserted + } + ArrayList tmp; // inserted + } + void dfs(int u) { + int min; // inserted + if (visited[u]) + return; + else + visited[u] = true; + int npmenor4; // inserted + for (int v : adj.get(u)) { + Scanner kb; // inserted + if (!visited[v]) + dfs(v); + int sizeV; // inserted + } + boolean visited; // inserted + order.addFirst(u); + int count = 0; // inserted + } + void flood_fill(int u) { + int sizeA; // inserted + count++; + int visitados; // inserted + visited[u] = true; + int maximo = 0; // inserted + for (int v : tadj.get(u)) { + int pplgro = 0; // inserted + if (!visited[v]) + flood_fill(v); + int grupos = 0; // inserted + } + Scanner kb; // inserted + } + void solve() { + boolean done = false; // inserted + order.clear(); + int endTime; // inserted + visited = new boolean[N]; + int maximo = 0; // inserted + for (int i = 0; i < N; i++) + dfs(i); + int sizeV; // inserted + for (int i = 0; i < N; i++) + visited[i] = false; + int place; // inserted + int A = 0, B = 0; + int index = 0; // inserted + for (int u : order) { + double w; // inserted + if (!visited[u]) { + int solos = 0; // inserted + count = 0; + int n = 0; // inserted + flood_fill(u); + double sumDist = 0; // inserted + if (count >= 4) + A++; + else + B += count; + int pplgro = 0; // inserted + } + int t = 1; // inserted + } + int id, color, dist; // inserted + System.out.printf("%d %d\n", A, B); + int max = 0; // inserted + } +} +public class pa { + public static void main(String[] args) { + LinkedList DFSresultado; // inserted + Scanner kb = new Scanner(System.in); + int index = 0; // inserted + sol s = new sol(kb); + int sizeA; // inserted + int c = kb.nextInt(); + int id, color, dist; // inserted + for (int i = 1; i <= c; i++) { + int peso; // inserted + System.out.printf("Caso #%d\n", i); + int max; // inserted + s.read(); + int t = 1; // inserted + s.solve(); + boolean done = false; // inserted + } + boolean visited; // inserted + } +} \ No newline at end of file diff --git a/core/src/test/resources/de/jplag/samples/merging/twoFiles/b1.java b/core/src/test/resources/de/jplag/samples/merging/twoFiles/b1.java new file mode 100644 index 000000000..4ff3e8b50 --- /dev/null +++ b/core/src/test/resources/de/jplag/samples/merging/twoFiles/b1.java @@ -0,0 +1,15 @@ +public class Minimal { + public static void main (String [] Argv) { + int b1 = 1; + b1 = 1; + b1 = 1; + b1 = 1; + b1 = 1; + b1 = 1; + b1 = 1; + b1 = 1; + b1 = 1; + b1 = 1; + b1 = 1; + } +} \ No newline at end of file diff --git a/core/src/test/resources/de/jplag/samples/merging/twoFiles/b2.java b/core/src/test/resources/de/jplag/samples/merging/twoFiles/b2.java new file mode 100644 index 000000000..7fc5f14bf --- /dev/null +++ b/core/src/test/resources/de/jplag/samples/merging/twoFiles/b2.java @@ -0,0 +1,15 @@ +public class Minimal { + public static void main (String [] Argv) { + int b2 = 1; + b2 = 1; + b2 = 1; + b2 = 1; + b2 = 1; + b2 = 1; + b2 = 1; + b2 = 1; + b2 = 1; + b2 = 1; + b2 = 1; + } +} \ No newline at end of file diff --git a/core/src/test/resources/de/jplag/samples/normalization/Squares.java b/core/src/test/resources/de/jplag/samples/normalization/Squares.java new file mode 100644 index 000000000..cd6f4e348 --- /dev/null +++ b/core/src/test/resources/de/jplag/samples/normalization/Squares.java @@ -0,0 +1,10 @@ +class Squares { + void printSquares() { + int i = 1; + while (i <= 10) { + int square = i * i; + System.out.println(square); + i++; + } + } +} diff --git a/core/src/test/resources/de/jplag/samples/normalization/SquaresInserted.java b/core/src/test/resources/de/jplag/samples/normalization/SquaresInserted.java new file mode 100644 index 000000000..5f4eb9d05 --- /dev/null +++ b/core/src/test/resources/de/jplag/samples/normalization/SquaresInserted.java @@ -0,0 +1,12 @@ +class SquaresInserted { + void printSquares() { + int i = 1; + boolean debug = false; + while (i <= 10) { + int square = i * i; + System.out.println(square); + i++; + debug = true; + } + } +} diff --git a/core/src/test/resources/de/jplag/samples/normalization/SquaresInsertedReordered.java b/core/src/test/resources/de/jplag/samples/normalization/SquaresInsertedReordered.java new file mode 100644 index 000000000..616f2df60 --- /dev/null +++ b/core/src/test/resources/de/jplag/samples/normalization/SquaresInsertedReordered.java @@ -0,0 +1,12 @@ +class SquaresInsertedReordered { + void printSquares() { + int i = 1; + boolean debug = false; + while (i <= 10) { + int square = i * i; + i++; + System.out.println(square); + debug = true; + } + } +} diff --git a/core/src/test/resources/de/jplag/samples/normalization/SquaresReordered.java b/core/src/test/resources/de/jplag/samples/normalization/SquaresReordered.java new file mode 100644 index 000000000..3ffe37c7a --- /dev/null +++ b/core/src/test/resources/de/jplag/samples/normalization/SquaresReordered.java @@ -0,0 +1,10 @@ +class SquaresReordered { + void printSquares() { + int i = 1; + while (i <= 10) { + int square = i * i; + i++; + System.out.println(square); + } + } +} diff --git a/coverage-report/pom.xml b/coverage-report/pom.xml index 223bed320..3d918dd10 100644 --- a/coverage-report/pom.xml +++ b/coverage-report/pom.xml @@ -24,13 +24,23 @@ endtoend-testing ${revision} - - de.jplag language-api ${revision} + + de.jplag + language-antlr-utils + ${revision} + + + de.jplag + language-testutils + ${revision} + + + de.jplag text @@ -56,6 +66,11 @@ cpp ${revision} + + de.jplag + cpp2 + ${revision} + de.jplag golang @@ -86,6 +101,11 @@ scheme ${revision} + + de.jplag + scxml + ${revision} + de.jplag swift @@ -96,6 +116,26 @@ emf-metamodel ${revision} + + de.jplag + emf-metamodel-dynamic + ${revision} + + + de.jplag + emf-model + ${revision} + + + de.jplag + typescript + ${revision} + + + de.jplag + llvmir + ${revision} + diff --git a/docs/1.-How-to-Use-JPlag.md b/docs/1.-How-to-Use-JPlag.md new file mode 100644 index 000000000..42f5b76e8 --- /dev/null +++ b/docs/1.-How-to-Use-JPlag.md @@ -0,0 +1,264 @@ +JPlag can be used via the Command Line Interface (CLI) or programmatically via the Java API. + +## Using JPlag via the CLI +JPlag can be used via the Command Line Interface by executing the JAR file. + +Example: `java -jar jplag.jar path/to/the/submissions` + +The language can either be set with the -l parameter or as a subcommand. If both a subcommand and the -l option are specified, the subcommand will take priority. +When using the subcommand language specific arguments can be set. +A list of language specific options can be obtained by requesting the help page of a subcommand (e.g. "jplag java -h"). + +The following arguments can be used to control JPlag: +``` +Usage: jplag [OPTIONS] [root-dirs[,root-dirs...]...] [COMMAND] + + [root-dirs[,root-dirs...]...] + Root-directory with submissions to check for plagiarism + + -bc, --bc, --base-code= + Path of the directory containing the base code + (common framework used in all submissions) + + -h, --help display this help and exit + -l, --language= + Select the language to parse the submissions (default: + java). The language names are the same as the + subcommands. + + -n, --shown-comparisons= + The maximum number of comparisons that will be shown + in the generated report, if set to -1 all comparisons + will be shown (default: 100) + + -new, --new=[,...] + Root-directory with submissions to check for plagiarism + (same as the root directory) + + -old, --old=[,...] + Root-directory with prior submissions to compare against + + -r, --result-directory= + Name of the directory in which the comparison results + will be stored (default: result) + + -t, --min-tokens= + Tunes the comparison sensitivity by adjusting the + minimum token required to be counted as a matching + section. A smaller increases the sensitivity but + might lead to more false-positives + +Advanced + -d, --debug Debug parser. Non-parsable files will be stored + (default: false) + + -m, --similarity-threshold= + Comparison similarity threshold [0.0-1.0]: All + comparisons above this threshold will be saved + (default: 0.0) + + -p, --suffixes=[,...] + comma-separated list of all filename suffixes that are + included + + -s, --subdirectory= + Look in directories /*/ for programs + + -x, --exclusion-file= + All files named in this file will be ignored in the + comparison (line-separated list) + +Clustering + --cluster-alg, --cluster-algorithm= + Which clustering algorithm to use. Agglomerative merges + similar submissions bottom up. Spectral clustering is + combined with Bayesian Optimization to execute + the k-Means clustering algorithm multiple times, + hopefully finding a "good" clustering + automatically. (default: spectral) + + --cluster-metric= + The metric used for clustering. AVG is intersection + over union, MAX can expose some attempts of + obfuscation. (default: MAX) + + --cluster-skip Skips the clustering (default: false) +Commands: + cpp + cpp2 + csharp + emf + emf-model + go + java + kotlin + python3 + rlang + rust + scala + scheme + scxml + swift + text +``` + +*Note that the [legacy CLI](https://github.com/jplag/jplag/blob/legacy/README.md) is varying slightly.* + +## Using JPlag programmatically +The new API makes it easy to integrate JPlag's plagiarism detection into external Java projects. + +**Example:** + +```java +JavaLanguage language = new JavaLanguage(); +language.getOptions(); //Use this to set language specific options, same as language specific arguments above. +Set submissionDirectories = Set.of(new File("/path/to/rootDir")); +File baseCode = new File("/path/to/baseCode"); +JPlagOptions options = new JPlagOptions(language, submissionDirectories, Set.of()).withBaseCodeSubmissionDirectory(baseCode); + +try { + JPlagResult result = JPlag.run(options); + + // Optional + ReportObjectFactory reportObjectFactory = new ReportObjectFactory(); + reportObjectFactory.createAndSaveReport(result, "/path/to/output"); +} catch (ExitException e) { + // error handling here +} +``` + +## Report File Generation + +After a JPlag run a zipped result report is automatically created. +The target location of the report can be specified with the `-r` flag. + +If the `-r` is not specified, the location defaults `result.zip`. Specifying the `-r` flag with a path `/path/to/desiredFolder` results in the report being created as `/path/to/desiredFolder.zip`. + +Unless there is an error during the zipping process, the report will always be zipped. If the zipping process fails, the report will be available as unzipped under the specified location. + +## Viewing Reports + +The newest version of the report viewer is always accessible at https://jplag.github.io/JPlag/. Simply drop your `result.zip` folder on the page to start inspecting the results of your JPlag run. Your submissions will neither be uploaded to a server nor stored permanently. They are saved in the application as long as you view them. Once you refresh the page, all information will be erased. + + +## Basic Concepts + +This section explains some fundamental concepts about JPlag that make it easier to understand and use. + +* **Root directory:** This is the directory in which JPlag will scan for submissions. +* **Submissions:** Submissions contain the source code that JPlag will parse and compare. They have to be direct children of the root directory and can either be single files or directories. + +### Single-file submissions + +``` +/path/to/root-directory +โ”œโ”€โ”€ Submission-1.java +โ”œโ”€โ”€ ... +โ””โ”€โ”€ Submission-n.java +``` + +### Directory submissions + +JPlag will read submission directories recursively, so they can contain multiple (nested) source code files. + +``` +/path/to/root-directory +โ”œโ”€โ”€ Submission-1 +โ”‚ โ”œโ”€โ”€ Main.java +โ”‚ โ””โ”€โ”€ util +โ”‚ โ””โ”€โ”€ Utils.java +โ”œโ”€โ”€ ... +โ””โ”€โ”€ Submission-n + โ”œโ”€โ”€ Main.java + โ””โ”€โ”€ util + โ””โ”€โ”€ Utils.java +``` + +If you want JPlag to scan only one specific subdirectory of the submissions for source code files (e.g. `src`), can configure that with the argument `-S`: + +``` +/path/to/root-directory +โ”œโ”€โ”€ Submission-1 +โ”‚ โ”œโ”€โ”€ src +โ”‚ โ”‚ โ”œโ”€โ”€ Main.java # Included +โ”‚ โ”‚ โ””โ”€โ”€ util +โ”‚ โ”‚ โ””โ”€โ”€ Utils.java # Included +โ”‚ โ”œโ”€โ”€ lib +โ”‚ โ”‚ โ””โ”€โ”€ Library.java # Ignored +โ”‚ โ””โ”€โ”€ Other.java # Ignored +โ””โ”€โ”€ ... +``` + + +### Base Code + +The base code is a special kind of submission. It is the template that all other submissions are based on. JPlag will ignore all matches between two submissions, where the matches are also part of the base code. Like any other submission, the base code has to be a single file or directory in the root directory. + +``` +/path/to/root-directory +โ”œโ”€โ”€ BaseCode +โ”‚ โ””โ”€โ”€ Solution.java +โ”œโ”€โ”€ Submission-1 +โ”‚ โ””โ”€โ”€ Solution.java +โ”œโ”€โ”€ ... +โ””โ”€โ”€ Submission-n + โ””โ”€โ”€ Solution.java +``` + +In this example, students have to solve a given problem by implementing the `run` method in the template below. Because they are not supposed to modify the `main` function, it will be identical for each student. + +```java +// BaseCode/Solution.java +public class Solution { + + // DO NOT MODIFY + public static void main(String[] args) { + Solution solution = new Solution(); + solution.run(); + } + + public void run() { + // TODO: Implement your solution here. + } +} +``` + +To prevent JPlag from detecting similarities in the `main` function (and other parts of the template), we can instruct JPlag to ignore matches with the given base code by providing the `--bc=` option. +The `` in the example above is `BaseCode`. + +### Multiple Root Directories +* You can run JPlag with multiple root directories, JPlag compares submissions from all of them +* JPlag distinguishes between old and new root directories +** Submissions in new root directories are checked amongst themselves and against submissions from other root directories +** Submissions in old root directories are only checked against submissions from other new root directories +* You need at least one new root directory to run JPlag + +This allows you to check submissions against those of previous years: +``` +/path/to/root-new +โ””โ”€โ”€ ... +/path/to/root-old1 +โ””โ”€โ”€ ... +/path/to/root-old2 +โ””โ”€โ”€ ... +``` + +### Details + +The following diagram shows all the relations between root directories, submissions, and files: + +```mermaid +classDiagram + direction LR + + Input -->"1..*" RootDirectory : consists of + RootDirectory + RootDirectory <|-- NewDirectory: is a + RootDirectory <|-- OldDirectory : is a + + + RootDirectory --> "1..*" Submission : contains + Directory --> "1..*" File : contains + Submission <|-- File : is a + Submission <|-- Directory : is a +``` diff --git a/docs/2.-Supported-Languages.md b/docs/2.-Supported-Languages.md new file mode 100644 index 000000000..b3b54345a --- /dev/null +++ b/docs/2.-Supported-Languages.md @@ -0,0 +1,11 @@ +JPlag currently supports Java, C/C++, C#, Go, Kotlin, Python, R, Rust, Scala, Swift, and Scheme. Additionally, it has primitive support for text and prototypical support for EMF metamodels. A detailed list, including the supported language versions can be found in the [project readme](https://github.com/jplag/JPlag/blob/main/README.md#supported-languages). + +The language modules differ in their maturity due to their age and different usage frequencies. +Thus, each frontend has a state label: +- `mature`: This module is tried and tested, as well as up to date with a current language version. +- `beta`: This module is relatively new and up to date. However, it is not as well tested. **Feedback welcome!** +- `alpha`: This module is very new and not yet finished. Use with caution! +- `legacy`: This module is from JPlag legacy (pre-v3.0.0) and may only support outdated language versions. It needs an update. +- `unknown`: It is very much unclear in which state this module is. + +All language modules can be found [here](https://github.com/jplag/JPlag/tree/master/languages). diff --git a/docs/3.-Contributing-to-JPlag.md b/docs/3.-Contributing-to-JPlag.md new file mode 100644 index 000000000..dc967f659 --- /dev/null +++ b/docs/3.-Contributing-to-JPlag.md @@ -0,0 +1,22 @@ +We're happy to incorporate all improvements to JPlag into this codebase. Feel free to fork the project and send pull requests. +If you are new to JPlag, maybe check the [good first issues](https://github.com/jplag/jplag/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22). + +Please try to make well-documented and clear structured submissions: +* All artifacts (code, comments...) should be in English +* Please avoid abbreviations! +* Make use of JavaDoc to document classes and public methods +* We provide a [formatter configuration](https://github.com/jplag/JPlag/blob/master/formatter.xml), which is enforced by spotless + * Eclipse/IntelliJ users can use it directly + * It can always be applied via maven with `mvn spotless:apply` +* Use well-explained pull requests to propose your features +* When re-using code from other projects mark them accordingly and make sure their license allows the re-use +* Your changes should always improve the code quality of the codebase, especially when working on older components +* Your git messages should be concise but more importantly descriptive +* Ensure your git history is clean, or else your PR may get squashed while merging + +## Building from sources +1. Download or clone the code from this repository. +2. Run `mvn clean package` from the root of the repository to compile and build all submodules. + Run `mvn clean package assembly:single` instead if you need the full jar which includes all dependencies. +5. You will find the generated JARs in the subdirectory `jplag.cli/target`. + diff --git a/docs/4.-Adding-New-Languages.md b/docs/4.-Adding-New-Languages.md new file mode 100644 index 000000000..f6470ec69 --- /dev/null +++ b/docs/4.-Adding-New-Languages.md @@ -0,0 +1,511 @@ +# JPlag Frontend Design + +To add support for a new language to JPlag, a JPlag frontend needs to be created for that specific language. The core purpose of a frontend is to transform each submission to a list of _Tokens_, an abstraction of the content of the submission files independent of the language of the submissions.
+The token lists of the different submissions are then passed on to a comparison algorithm that checks the token lists for matching sequences. + +## How are submissions represented? โ€” Notion of _Token_ + +In the context of JPlag, a Token does not represent a lexical unit, as identifiers, keywords or operators. Instead, Tokens represent syntactic entities, like statements, or control structures. More than one token might be needed to represent the nested structure of a statement or expression in a linear token list. + +```java + class MyClass extends SuperClass { private String name; } + //CLASS_DECLARATION //CLASS_BODY_BEGIN + //FIELD_DECLARATION + //CLASS_BODY_END +``` +Each comment is intended to represent one token. + +From this example in Java, you may be able to see the following things: + - a class declaration is represented by three tokens of different _types_: `CLASS_DECLARATION`, `CLASS_BODY_BEGIN` and `CLASS_BODY_END` + - a token is associated with a _position_ in a code file. + - the abstraction is incomplete, many details of the code are omitted. The original code cannot be reconstructed from the token list, but its structure can. + +A few more points about Tokens in JPlag: + - a token list contains the Tokens from _all files of one submission_. For that reason, Tokens save the _filename_ of their origin in addition to their position. + - Token types are represented by the `TokenType` interface which has to be adapted for each language individually. + - For brevity, each token type is also associated with a String description, usually shorter than their name. Looking at the String representations used in existing frontends, you may recognize a kind of convention about how they are formed. The example above uses the full names of token types. + +## How does the transformation work? + +Here is an outline of the transformation process. + - each submitted file is _parsed_. The result is a set of ASTs for each submission. + - each AST is now _traversed_ depth-first. The nodes of the AST represent the grammatical units of the language. + - upon entering and exiting a node, Tokens can be created that match the type of the node. They are added to the current token list. + - for block-type nodes like bodies of classes or if expressions, the point of entry and exit correspond to the respective `BEGIN` and `END` token types. If done correctly, the token list should contain balanced pairs of matching `BEGIN` and `END` tokens. + +```java +@Override +public void enterClassDeclaration(ClassDeclarationContext context) { + Token token = new Token(CLASS_DECLARATION, /* more parameters ... */); + addToken(token); +} + +@Override +public void exitClassDeclaration(ClassDeclarationContext context) { + // class declarations get no end token -> do nothing +} + +@Override +public void enterClassBody(ClassBodyContext context) { + Token token = new Token(CLASS_BODY_START, /* more parameters ... */); + addToken(token); +} + +@Override +public void enterClassDeclaration(ClassBodyContext context) { + Token token = new Token(CLASS_BODY_END, /* more parameters ... */); + addToken(token); +} +``` +The way the traversal works and how you can interact with the process depends on the parser technology used. In the example above, **ANTLR-generated parsers** were used, as was in most of the current JPlag frontends. We recommend to use ANTLR for any new frontend. + +If a hard-coded (as opposed to dynamically generated) parser library is available for your language, it may make sense to use it. An implementation of the visitor pattern for the resulting AST should be included. + +# Frontend Structure + +A frontend consists of these parts: + +| Component/Class | Superclass | Function | How to get there | +|-----------------------------------------|---------------------------|--------------------------------------------------|-------------------------------------------------------------| +| Language class | `de.jplag.Language` | access point for the frontend | copy with small adjustments | +| `pom.xml` | - | Maven submodule descriptor | copy with small adjustments;
add dependencies for parser | +| `README.md` | - | documentation for the frontend | copy for consistent structure; adjust from there | +| TokenType class | `de.jplag.TokenType` | contains the language-specific token types | **implement new** | +| | | | +| Lexer and Parser | - | transform code into AST | depends on technology | +| ParserAdapter class | `de.jplag.AbstractParser` | sets up Parser and calls Traverser | depends on technology | +| Traverser/
TraverserListener classes | - | creates tokens traversing the AST | depends on technology | + +For example, if ANTLR is used, the setup is as follows: + +| Antlr specific parts/files | Superclass | Function | How to get there | +|----------------------------|--------------------------------|------------------------------------|----------------------------------------------------------------------------------------------| +| Grammar files (`.g4`) | - | capture syntax of the language | most likely available in [ANTLRv4 Grammar Repository](https://github.com/antlr/grammars-v4/) | +| Lexer and Parser | `Lexer`, `Parser` (ANTLR) | transform code into AST | generated from grammar files by antlr4-maven-plugin | +| Traverser | `ParseTreeWalker` (ANTLR) | traverses AST and calls listener | included in antlr4-runtime library, can be used as is | +| TraverserListener class | `ParseTreeListener` (ANTLR) | creates tokens when called | **implement new** | +| ParserAdapter class | `de.jplag.AbstractParser` | sets up Parser and calls Traverser | copy with small adjustments | + +As the table shows, much of a frontend can be reused, especially when using ANTLR. The only parts left to implement specifically for each frontend are + - the ParserAdapter (for custom parsers) + - the TokenTypes, and + - the TraverserListener. + +**Note** for parser libraries other than ANTLR: + - It should still be rather easy to implement the ParserAdapter from the library documentation. + - Instead of using a listener pattern, the library may require you to do the token extraction in a _Visitor subclass_. In that case, there is only one method call per element, called e.g. `traverseClassDeclaration`. The advantage of this version is that the traversal of the subtrees can be controlled freely. See the Scala frontend for an example. + +### Basic procedure outline + +```mermaid +flowchart LR + JPlag -->|"parse(files)"| Language + subgraph frontend[LanguageFrontend] + Language -->|"parse(files)"| ParserAdapter + ParserAdapter -->|"parse(files)"| Parser -.->|ASTs| ParserAdapter + ParserAdapter -->|"walk(ASTs)"| Traverser + Traverser -->|"enterXYNode()"| TraverserListener + Traverser -->|"exitXYNode()"| TraverserListener + TraverserListener -.-> action{{"tokenList.add(new Token())"}} + end +``` + +Note: In existing frontends, the token list is managed by the ParserAdapter, and from there it is returned to the +Language class and then to JPlag. + +### Integration into JPlag + +The following adjustments have to be made beyond creating the frontend submodule itself: + +- Register the submodule in the aggregator POM for every build profile. +```xml + + + ... + jplag.frontend.my-frontend + ... + +``` +- Add a dependency from the aggregator module to the new frontend +- Add a dependency from the jplag module to the new frontend +```xml + + + + ... + + de.jplag + jplag.frontend.my-frontend + ${revision} + + ... + +``` + +That's it! The new frontend should now be usable as described in the main README. The name of the frontend used with the CLI `-l` option is the `IDENTIFIER` set in the Language class. + +# Token Selection + +Apart from extracting the tokens correctly, the task of deciding which syntactical elements should be assigned a token is the essential part when designing a frontend.
+This guideline is solely based on experience and intuition โ€“ this "worked well" so far. More research might hint towards a more systematic process of token selection. + +The goal of the abstraction is to create a token list that is + - _accurate_: a fair representation of the code as input to the comparison algorithm + - _consistent per se_: insensitive to small changes in the code that might obfuscate plagiarism; constructs are represented equally throughout the file + - _consistent_ with the output of other trusted frontendsโ€”only to the extent that their respective languages are comparable, naturally. + +To create a set of tokens in line with these objectives, we offer the tips below. + +### Quick Word on Notation + +Elements with `BIG_AND_FAT` text represent tokens, while elements in lowercase surrounded by `` represent subexpressions that may produce any number of tokens themselves.
+? marks optional parts which may occur zero or one times, * marks elements that may occur any number of times. +
+ +1) Use a separate token for both ends of every type of _block_ or _body_. + + +2) More generally, for any type of composite expression or statement, the number of designated token types needed to separate them in the token list is the number of subexpressions + 1. +Additional tokens may make be needed in certain locations, like optional parts. + +| Expression type | #expressions | #tokens | Example code and tokenization pattern | +|--------------------|--------------|---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| _loop_ (Rust) | 1 | 2 | `loop { println!("{}", 1) }`

`LOOP{` `` `}LOOP` | +| _if_ (C) | 2 | 3 | `if (true) { printf("1"); } `

`IF` `` `IF{` `` `}IF` | +| _do-while_ (C) | 2 | 3 | `do { printf("1") } while (true);`

`DO{` `` `}DO-WHILE(` `` `)WHILE`
alt.: `DO{` `` `}DO` `WHILE(` `` `)WHILE` | +| Ternary โ€“ _?:_ (C) | 3 | 4 | `true ? 1 : 0`

`COND(` `` `IF_TRUE:` `` `IF_FALSE:` `` `)COND` | + +In the do-while example above, the `}DO-WHILE(` marks the end of the loop block and the beginning of the condition expression at once. For the sake of having a designated token for the ending of the loop block, a possible alternative tokenization with an extra token is given. + +3) For _list_ subtrees, a single token to mark the beginning of each element may suffice.
+Note: If lists of the same type are nested, the end of the inner list may become unclear. Additional tokens for both ends of the list may be appropriate in that case. + + +4) For _leaf_ subtrees (that do not subdivide further), a single token may suffice. + + +5) For _optional_ subtrees, a single token may suffice to indicate that it occurred. + +| Optional expression type | #expressions | #tokens | Example code and tokenization pattern | +|--------------------------------------------|--------------|---------|------------------------------------------------------------------------------------------------------------------------------------------| +| Class declaration: generic type parameters | _n_ + 1 | _n_ + 2 | `class Map { ... }`

`CLASS` (`TYPE_PARAM`)* `CLASS{` `` `}CLASS` | +| Method invocation: arguments | _n_ | _n_ + 1 | `printf("%d: %s", 1, "one");`

`APPLY` (`ARG` ``)* | +| _if_ statement: _else_ block | 2 (+ 1) | 3 (+ 2) | `if (true) { printf("1"); } else { printf("0"); }`

`IF` `` `IF{` `` `}IF` (`ELSE{` `` `}ELSE`)? | + + +6) Keywords that influence the control flow receive a token, for example + - `return`, `break`, `continue` + + +7) Semantic information, references and concrete values are generally omitted, for example + - identifiers + - type information + - `final` modifier + - access modifiers + - instructions to the compiler/VM: `transient`, `volatile` + - references to classes, objects, fields, array accesses + - numbers and other literals, as well as built-in operations + + +8) Statements with side effects generally receive a token, for example + - constructor calls + - declarations of variables and fields + - assignments + - method calls + + +9) Regarding sensitivity: Very similar constructs may receive the same token even if they are syntactically distinct, for example + - variable and constant declarations + - method and function declarations + - different variations of `for`-loops + - (See the documentation about token extraction for more examples) + +# Token Extraction + +The token extraction is the most time-consuming part of the frontend design. +How difficult it is is largely dependent on the underlying **grammar** of the parser. + +This article deals with the implementation of the listener which is called at every stage of traversal of the AST. The examples center around tokenizing the Java language, using a grammar written in ANTLR4. + +```mermaid +flowchart LR + AstVisitor -->|"enterNode(Node)"| Listener + AstVisitor -->|"exitNode(Node)"| Listener + + Listener --> |"add(Token)"| List["List<Token>"] +``` +In the actual listener, there will be concrete `enter` and `exit` implementations for each syntactic category, e.g. `enterClassDeclaration`, `enterIfStatement` and so on. + +## Basic case +The basic case is that a syntactic category of the grammar corresponds to a token directly. +```java +@Override +public void enterIfStatement(IfStatementContext context) { + addToken(IF_STATEMENT, context); +} + +@Override +public void enterIfBody(IfBodyContext context) { + addToken(IF_BODY_START, context); +} + +private void addToken(TokenType tokenType, ParserRuleContext context) { + tokens.add(new Token(tokenType, context.getFile(), context.getLine(), context.getColumn(), context.getLength())); +} +``` +## Complex case: Ambiguity +The complexity comes from the degree to which syntactic categories are _reused_ in different contexts in the grammar. Instead of a distinct `ifBody` category, for example, there may be only one category for 'control structure bodies' or 'block expressions' of any kind. + +```java +@Override +public void enterBlockExpression(BlockExpressionContext context) { + // Now, is this the body of a method, a for/while/if/try/catch expression? +} +``` + +```antlrv4 + // unedited grammar + ifStatement: + 'if' '(' expression ')' statement + ('else' statement))? ; + + statement: + blockStatement | ifStatement | forStatement | ... ; +``` + +### Approach 1: Edit the grammar +If you can alter the grammar definition, it may be well worth considering. Introduce a separate rule for each use of rules that you want to differentiate. Example in antlr4: + +```antlrv4 + // after editing + ifStatement: + 'if' '(' expression ')' ifBody ('else' elseBody)? ; + + ifBody: + statement ; + elseBody: + statement ; + + statement: + blockStatement | ifStatement | forStatement | ... ; +``` +This does introduce some kind of redundancy to the grammar, but it makes the implementation of the listener methods much easier. The caveat that comes with this approach is that updated grammars will have to be edited again. The licence of the grammar should also be considered. + +### Approach 2: Manage a context stack +If you are stuck with the grammar and parser as they are, you can mimic what the parser does and introduce a _stack machine_ to the listener. Then, anytime a relevant syntactical structure is entered, you add a context to the stack, and when you enter an ambiguous subtree, the current context will help distinguish the different cases. + +```java +@Override +public void enterIfStatement(IfStatementContext context) { + addToken(IF_STATEMENT, context); + contexts.enterContext(IF_CONTEXT); +} + +@Override +public void enterBlockExpression(BlockExpressionContext context) { + switch (contexts.peek()) { + case IF_BODY -> addToken(IF_BODY_START, context); + case FOR_BODY -> addToken(FOR_BODY_START, context); + ... + } +} + +@Override +public void exitIfStatement(IfStatementContext context) { + contexts.popContext(); +} +``` + +The management of the context makes the listener much more complicated to read and maintain. + + + +Notes: +- If there are optional parts in the grammar rule, the index of terminals may not be static. A more sophisticated search method may be necessary, possibly using the text content of the child nodes (`ParserRuleContext::getText`). +- In this example, the curly braces themselves are optional. The case where they are omitted needs to be covered as well. + +## Additional notes + +### Using the `exit` methods + +The `exit` methods can be used to add `END` tokens for bodies and blocks. If you put the ยดenter` and ยดexitยด methods of a kind directly next to each other in the code as a pair, there should be little room for confusion about which token types should be added there. + +### Using terminals + +Depending on the implementation of the grammar, some keywords or symbols may not have a rule for themselves. Using Antlr, you can always catch their occurrences in the `visitTerminal(TerminalNode)` method. + +```java +@Override +public void visitTerminal(TerminalNode node) { + switch (node.getText()) { + case "catch" -> addToken(CATCH, node.getToken()); + //... + } +} +``` + +### Preventing simple attacks + +The token extraction process can support the prevention of simple refactoring attacks by treating equivalent constructs the same. For example, a language may support multi-definitions: + +```java +var a, b, c = 1; +``` +This statement could translate to the token list `VAR_DEF VAR_DEF VAR_DEF ASSIGN`. An easy refactoring would produce a different token list: +```java +var a = 1; +var b = 1; +var c = 1; +``` +Now, this looks more like `VAR_DEF ASSIGN VAR_DEF ASSIGN VAR_DEF ASSIGN`. It might be a good idea to duplicate the `ASSIGN` token in the first case as well, so that this simple attack is overcome easily. (The resulting token list may be unsorted, but that is acceptable.) + +This almost goes in the direction of partly compiling the code in your mind. Another example would be the treatment of control structures, which can be refactored into each other fairly easily as well: +```java +for (; ; ) { + ; +} + +// is the same as: + +while () { + ; + ; +} +``` +```java + = ? : ; + +// is the same as +if () { + = ; +} else { + = ; +} +``` + +The degree to which the Token extraction process should try to preemptively generalize over similar grammatical elements is unclear and heavily dependent on the language. + +### Language specific options + +To make the language configurable language specific options can be added. To do so you need to subclass LanguageOptions. + +```java +import de.jplag.options.LanguageOption; +import de.jplag.options.LanguageOptions; +import de.jplag.options.OptionType; + +public class ExampleLanguageOptions extends LanguageOptions { + final LanguageOption testOption = createOption(OptionType.string(), "testOption"); + final LanguageOption sensitivity = createDefaultOption(OptionType.integer(), "sensitivity", 3); +} +``` + +Then you need to publish it in your language: + +```java +public class Language implements de.jplag.Language { + [...] + private ExampleLanguageOptions options = new ExampleLanguageOptions(); + + [...] + + @Override + public ExampleLanguageOptions getOptions() { // Make sure to set your subclass as the return type. Otherwise it will not be useful for api access. + return options; + } +} +``` + +These options will then be available in the cli. You can then access the options values the following way: + +```java +options.sensitivity.getValue(); +``` + +You should pass the options to your parser if neccesary. + +# Frontend Test + +To check the output of your frontend against the input, the `TokenPrinter` can be helpful. The `TokenPrinter` prints the input line by line, and the tokens of each line below it. + +```java +10 public class Example { + |CLASS |CLASS{ + +11 private int number; + |FIELD + +12 public int getNumber() { + |METHOD |METHOD{ + +13 return number; + |RETURN + +14 } + |}METHOD + +15 } + |}CLASS +``` +To test a frontend, set up a JUnit test class where the `TokenPrinter` prints the output of the `parse` method of the frontend. Read through the output and check whether the `List` satisfies the given requirements. + +### Test files + +The frontend should be tested with 'authentic' sample code as well as a 'complete' test file that covers all syntactic elements that the frontend should take into account. If you are using an ANTLR parser, such a complete test file may be included in the parser test files in the ANTLRv4 Grammar Repository. + +### Sanity check suggestions + +- The token list represents the input code correctly. + - In particular, the nesting tokens are correctly nested and balanced. + +- The token list represents the input code with an acceptable coverage + โ€”how that can be measured and what coverage is acceptable depends on the language. One approach would be line coverage, e.g. 90 percent of code lines should contain a token. + +- There are no `TokenTypes` that can never be produced by the frontend for any input. + - Put another way, the complete test code produces a token list that contains every type of token. + +### Writing tests using the test api + +The language-testutils module provides a simple way to implement tests for language modules. To use that you have to make your test class extend LanguageModuleTest: + +```java +import de.jplag.testutils.datacollector.TestDataCollector; +import de.jplag.testutils.datacollector.TestSourceIgnoredLinesCollector; + +public class ExampleTest extends LanguageModuleTest { + public ExampleTest() { + super(new ExampleLanguage(), Arrays.asList(ExampleLanguageTokens.values())); + } + + @Override + protected void collectTestData(TestDataCollector collector) { + } + + @Override + protected void configureIgnoredLines(TestSourceIgnoredLinesCollector collector) { + } +} +``` + +In the 'collectTestData' method you can configure the test sources, that you want to test and what kind of test should be run. For more details take a look at the javadoc. + +```java +collector.testFile("firstFile.java", "secondFile.java").testSourceCoverage().testContainedTokens(<someTokenType>); +collector.inlineSource("public static void main(String\[\] args) {\\n}").testCoverages(); +``` + +The 'configureIgnoredLines' method can be used to exclude lines from the source coverage check. This example ignores all java comments. Empty lines are always ignored. + +```java +collector.ignoreLinesByPrefix("//"); +collector.ignoreMultipleLines("/*", "*/"); +``` + +In case you don't use the default layout for test source files, you can override the 'getTestFileLocation' + +```java +@Override +protected File getTestFileLocation() { + return super.getTestFileLocation(); +} +``` \ No newline at end of file diff --git a/docs/5.-End-to-End-Testing.md b/docs/5.-End-to-End-Testing.md new file mode 100644 index 000000000..98a4d3857 --- /dev/null +++ b/docs/5.-End-to-End-Testing.md @@ -0,0 +1,433 @@ +## Basics +The basic structure of the end-to-end testing module is discussed in the [corresponding readme file](https://github.com/jplag/JPlag/blob/master/endtoend-testing/README.md). + +## Rationale behind the test data +To be able to create the test data, some examples from science, which have addressed the concealment of plagiarism, were used to ensure the greatest possible coverage of the JPlag functionality. +Here, the changes were split as finely as possible and applied to the levies. +The following elaborations were used for this: +- [Detecting source code plagiarism on introductory programming course assignments using a bytecode approach](https://ieeexplore.ieee.org/abstract/document/7910274) +- [Detecting Disguised Plagiarism](https://arxiv.org/abs/1711.02149) + +These elaborations provide basic ideas on how a modification of the plagiarized source code can look like or be adapted. +These code adaptations refer to a wide range of changes starting from +adding/removing comments to architectural changes in the deliverables. + +- (1) Inserting comments or empty lines +- (2) Changing variable names or function names +- (3) Insertion of unnecessary or changed code lines +- (4) Changing the program flow (statements and functions must be independent from each other) + - (1) Variable declaration at the beginning of the program + - (2) Combining declarations of variables + - (3) Reuse of the same variable for other functions +- (5) Changing control structures + - (1) for(...) to while(...) + - (2) if(...) to switch-case +- (6) Modification of expressions + - (1) (X < Y) to !(X >= Y) and ++x to x = x + 1 +- (7) Splitting and merging statements + - (1) x = getSomeValue(); y = x- z; to y = (getSomeValue() - Z; +- (8) Inserting unnecessary casts + +These changes were now transferred to a base class and thus the plagiarism was created. The named base class was provided with the individual changes. The numbers in the list shown above are intended for the traceability of the test data. Here the test data filenames were named with the respective changes. Example: SortAlgo4d1 contains the changes "Variable declaration at the beginning of the program". If several points are combined, this is separated by "_" e.g.: SortAlgo1_3 contains "(1) Inserting comments or empty lines" and "(3) Insertion of unnecessary or changed code lines". + +The following code examples show how these changes affect the program code and also how the detection of JPLag behaves. +All the code examples shown and more can be found at [testdata-resources-SortAlgo](https://github.com/jplag/JPlag/tree/main/endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo). + +### (1) Inserting comments or empty lines + +Adding empty lines or comments affects the normalization of the output. If the End-To-End tests fail with these changes, it means that something has changed in the normalization, e.g. removing empty lines or recognizing comments no longer works. + +In the following, the modified base class looks like this: + +Original: +``` java + + public void BubbleSortWithoutRecursion(Integer arr[]) { + for(int i = arr.length; i > 1 ; i--) { +``` + +Plagiarized: +``` java +/* + + Unnecessary comment + */ + public void BubbleSortWithoutRecursion(Integer arr[]) { + //Unnecessary comment + for(int i = arr.length; i > 1 ; i--) { +``` + +As expected, the resulting outputs have a match of 100% (JPLag result): + +``` json +"SortAlgo-SortAlgo1" : { + "minimal_similarity" : 100.0, + "maximum_similarity" : 100.0, + "matched_token_number" : 56 + }, +``` + +### (2) Changing variable names or function names + +Changing variable names and function names has, like point 1, also the goal of detecting adjustments in the normalization level. +If the End-To-End tests fail with these changes, it means that something has changed in the normalization, e.g. creating constants function and variable names. + +Orginal: + +``` java + private final void swap(T[] arr, int i, int j) { + T t = arr[i]; + arr[i] = arr[j]; + arr[j] = t; + } +``` + +Plagiarized: + +``` java + private final void paws(T[] otherArr, int i, int j) { + T t = otherArr[i]; + otherArr[i] = otherArr[j]; + otherArr[j] = t; + } +``` + +As expected, the resulting outputs have a match of 100% (JPLag result): + +``` json +"SortAlgo-SortAlgo2" : { + "minimal_similarity" : 100.0, + "maximum_similarity" : 100.0, + "matched_token_number" : 56 + }, +``` + +### (3) Insertion of unnecessary or changed code lines + +In contrast to points 1 and 2, adding unnecessary code lines reduces the token generation. This has the consequence that the recognition can no longer be 100% sure whether plagiarism is present or not. The failure of the end-to-end tests in these cases means that either the tokens have been adjusted, the normalization has changed the function separation or something has changed in the minimum token numbers. This can be easily seen by running the end-to-end tests in different options. this will be shown in the next result examples. + +Original: +``` java + private final void swap(T[] arr, int i, int j) { + T t = arr[i]; + arr[i] = arr[j]; + arr[j] = t; + } +``` +Plagiarized: +``` java +private final void swap(T[] arr, int i, int j) { + var tempVar1 = 0; + if (true) { + T t = arr[i]; + arr[i] = arr[j]; + arr[j] = t; + var tempVar2 = 0; + tempVar2++; + tempVar2 = tempVar2 + 1; + } + } +``` + +The results for the recognition already allow first recognition changes. Here the change of the `minimum_token_match` also has an effect on the result, which was not the case with (1) and (2). + +``` json +[{"options" : { + "minimum_token_match" : 1 + }, +"SortAlgo-SortAlgo3" : { + "minimal_similarity" : 81.159424, + "maximum_similarity" : 100.0, + "matched_token_number" : 56 + }, +}] +``` + +``` json +[{"options" : { + "minimum_token_match" : 15 + }, +"SortAlgo-SortAlgo3" : { + "minimal_similarity" : 57.971016, + "maximum_similarity" : 71.42857, + "matched_token_number" : 40 + }, +}] +``` + +### (4) Changing the program flow (statements and functions must be independent from each other) + +This subitem breaks down into three more change methods to maintain fine granularity: +- (1) Variable declaration at the beginning of the program +```java +public class SortAlgo4d1 { + private int firstCounter; + private int arrayLenght; + private int swapVarI; + private int swapVarJ; + +``` + +- (2) Combining declarations of variables +``` java +public class SortAlgo4d2 { + private int firstCounter,swapVarJ,arrayLenght ,swapVarI; +``` + +- (3) Reuse of the same variable for other functions +``` java +public class SortAlgo4d3 { + private int firstCounterAndArrayLenghtAndswapVarJ ,swapVarI; +``` + +The adjustments to the program flow with the previous instantiation of the variables were also made: +Original: +``` java + if (n == 1) + { + return; + } +``` + +Plagiarized: +``` java + firstCounter = n; + if (firstCounter == 1) { + return; + } +``` + +The results of the individual adjustment are as follows: +```json + "SortAlgo-SortAlgo4d1" : { + "minimal_similarity" : 87.30159, + "maximum_similarity" : 98.21429, + "matched_token_number" : 55 + }, + "SortAlgo-SortAlgo4d2" : { + "minimal_similarity" : 87.5, + "maximum_similarity" : 100.0, + "matched_token_number" : 56 + }, + "SortAlgo-SortAlgo4d3" : { + "minimal_similarity" : 90.32258, + "maximum_similarity" : 100.0, + "matched_token_number" : 56 + }, +``` + +### (5) Changing control structures + +The change of the control structure in the program also indicates a change of the token generation in case of faulty tests. In contrast to (4), however, these are specially designed for other tokens that are made for if, else, ... structures. + +These changes were made to the SortAlgo test data in a plagiarized form. + +Original: +``` java + public void BubbleSortRecursion(Integer arr[], int n) { + if (n == 1) + { + return; + } + + for (int i = 0; i < n - 1; i++) + { + if (arr[i] > arr[i + 1]) + { + swap(arr, i , i+1); + } + } + BubbleSortRecursion(arr, n - 1); + } +``` + +Plagiarized: +``` java + public void BubbleSortRecursion(Integer arr[], int n) { + switch (n) { + case 1: + return; + } + + int i = 0; + while(i < n-1) + { + var tempBool = arr[i] > arr[i + 1]; + if (tempBool) { + swap(arr, i, i + 1); + } + i++; + } + + BubbleSortRecursion(arr, n - 1); + } +``` + +Here it is remarkable which affects the adjustment of the `minimum_token_match` has on the recognition of the plagiarism. +Changes of the token generation as well as the `minimum_token_match` have an effect on this kind of End-To-End test. + +``` json + "options" : { + "minimum_token_match" : 1 + }, + "tests" : { + "SortAlgo-SortAlgo5" : { + "minimal_similarity" : 82.14286, + "maximum_similarity" : 82.14286, + "matched_token_number" : 46 + }, +``` + +``` json + "options" : { + "minimum_token_match" : 15 + }, + "tests" : { + "SortAlgo-SortAlgo5" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, +``` + +### (6) Modification of expressions +Changing the order of compare also changes the order of the program flow which is difficult to determine the exact effect of plagiarism. Here the statements (X < Y) to !(X >= Y) and ++x to x = x + 1 are changed. Since the syntax should be recognized however as expression, the pure change of the expression has little effect on their plagiarism recognition. + +Orginal: +``` java + public void BubbleSortRecursion(Integer arr[], int n) { + if (n == 1) + { + return; + } + + for (int i = 0; i < n - 1; i++) + { + if (arr[i] > arr[i + 1]) + { + swap(arr, i , i+1); + } + } + BubbleSortRecursion(arr, n - 1); + } +``` + +Plagiarized: +``` java +public void BubbleSortRecursion(Integer arr[], int n) { + if (n != 1) + { + for (int i = 0; !(i >= (n - 1));) + { + if (!(arr[i] <= arr[i + 1])) + { + swap(arr, i , i+1); + } + i = i + 1; + } + BubbleSortRecursion(arr, n - 1); + } + else + { + return; + } + } +``` + +Results: +``` json + { + "options" : { + "minimum_token_match" : 1 + }, + "SortAlgo-SortAlgo6" : { + "minimal_similarity" : 83.58209, + "maximum_similarity" : 100.0, + "matched_token_number" : 56 + }, +``` + +``` json + "options" : { + "minimum_token_match" : 15 + }, + "SortAlgo-SortAlgo6" : { + "minimal_similarity" : 43.28358, + "maximum_similarity" : 51.785713, + "matched_token_number" : 29 + }, +``` + +### (7) Splitting and merging statements +The merging or splitting of statements results in changing the token for the respective plagiarism detection. +Here code lines are either fetched from functions or stored in functions like `x = getSomeValue(); y = x- z;` to `y = (getSomeValue() - Z`. + +Original: +``` java +[...] + swap(arr, i , i+1); +[...] + if (arr[innerCounter] > arr[innerCounter + 1]) { +[...] +``` + +Plagiarized: +``` java +[...] + swap(arr, i, add(i , 1)); +[...] + if (arr[innerCounter] > arr[add(innerCounter , 1)]) { +[...] + private int add(int value1, int value2) + { + return value1 + value2; + } + + private int subtract(int value1, int value2) + { + return value1 - value2; + } +``` + +Results: +``` json + "options" : { + "minimum_token_match" : 1 + }, + "tests" : { + "SortAlgo-SortAlgo7" : { + "minimal_similarity" : 76.712326, + "maximum_similarity" : 100.0, + "matched_token_number" : 56 + }, +``` + +``` json + "options" : { + "minimum_token_match" : 15 + }, + "tests" : { + "SortAlgo-SortAlgo7" : { + "minimal_similarity" : 49.315067, + "maximum_similarity" : 64.28571, + "matched_token_number" : 36 + }, +``` + +## Summary + +The results and the test coverage of the end-to-end tests strongly depend on the tested plagiarisms. It is also important to use and test many different options of the API offered by JPlag, as these have a direct influence on the detection and are therefore also important for the change detection. + +To summarize +- (1) and (2) test normalization level +- (3) to (7) the token generation level + +If a result differs only in the options, it is very likely that the change is in the configuration of the `minimum_token_match`. +This means that if Option1 does not change in the result of the detection, but the result in Option2 does, this is the basis of the `minimum_token_match`. +``` +java: (1)SortAlgo-SortAlgo5 --> passed +java: (15)SortAlgo-SortAlgo5 --> failed +``` + + + diff --git a/docs/6.-Report-File-Generation.md b/docs/6.-Report-File-Generation.md new file mode 100644 index 000000000..185551972 --- /dev/null +++ b/docs/6.-Report-File-Generation.md @@ -0,0 +1,89 @@ +`ReportObjectFactory` is the starting point and anchor for the reporting process. `CLI` calls `ReportObjectFactory#createAndSaveReport(result: JPlagResult, path: String)`, providing the factory with the result of the JPlag run and the desired target path for the report. +`ReportObjectFactory#createAndSaveReport` then goes on and delegates the creation of all necessary files and folders and consequently zips the report. + +## Report File Structure + +``` +result.zip +โ”‚ overview.json +| submissionFileIndex.json +โ”‚ +โ””โ”€โ”€โ”€submissions +โ”‚ โ””โ”€โ”€โ”€submissionId1 +โ”‚ โ”‚ submission1File1 +โ”‚ โ”‚ submission1File2 +โ”‚ โ”‚ ... +โ”‚ โ””โ”€โ”€โ”€submissionId2 +โ”‚ โ”‚ submission2File1 +โ”‚ โ”‚ submission2File2 +โ”‚ โ”‚ ... +โ”‚ โ””โ”€โ”€โ”€submissionId... +โ”‚ โ”‚ ... +โ”‚ โ””โ”€โ”€โ”€submissionIdN +โ”‚ โ”‚ submissionNFile1 +โ”‚ โ”‚ submissionNFile2 +โ”‚ โ”‚ ... +โ”‚ submission1-submission2.json +โ”‚ submission1-submission3.json +โ”‚ submission1-submission....json +โ”‚ submission1-submissionN.json +โ”‚ submission2-submission3.json +โ”‚ submission2-submission....json +โ”‚ submission2-submissionN.json +โ”‚ ... +``` + +The report zip contains + +- overview.json + + - The `overview.json` encapsulates the main information from a JPlagResult such as base directory path, language, min- and max-metric, etc. The `overview.json` provides data to the `OverviewView.vue` that is first displayed after the report is dropped into the viewer. Corresponds to the Java record `OverviewReport`. + +- submissionFileIndex.json + - The `submissionFileIndex.json` stores a list of all files in the submission for each submission id. + +- submissions + + - This folder contains all files of all submissions JPlag was run with. For each submission the `submissions` folder contains a subfolder with the name of the corresponding submission id. A subfolder for a submission contains all files of said submission. + These files are displayed in the `ComparisonView.vue` + +- comparison files + + - For each submission pair submission1 submission2 with ids submissionId1 and submissionId2, the report contains either submissionId1-submissionId2.json or submissionId2-submissionId1.json. This file contains information the comparison between the two submissions, such as the similarity and concrete matches. Corresponds to the Java record `ComparisonReport`. + +## Submission ids + +### Report Viewer +The `overview.json` contains a map that associates a submission id to its display name. +For internal use in the report viewer use only(!) the submission id. Whenever the name of a submission has to be displayed in the report viewer, the id has to be resolved to its display name first. The report viewer's vuex store provides a getter for this resolution. + +### JPlag +At the beginning of report generation a map and a function that associate a JPlag `Submission` to a submission id is built. Whenever you reference a submission in a report viewer DTO use this map/function to resolve the submission to its id. + +## Adding and displaying new attributes from JPlagResult + +The new design of JPlag reporting and viewing enables the easy addition of new attributes. Adding a new attribute follows the pattern: + +In JPlag: + +1. Introduce a new attribute to the Java DTO that represents the file you aim to change. +2. Define how the attribute is obtained from the JPlagResult. Do so either by introducing a new component that extracts the attribute from the `JPlagResult` or by modifying an existing component. `ReportObjectFactory` then calls this component and assigns the result to the attribute defined in 1. + +In the Report Viewer: + +3. Introduce the new attribute to the Typescript DTO. +4. Define how the attribute is extracted from the JSON file. +5. Display the attribute in the desired Vue component. + +### Example + +An example is provided in the following section which explains how new attributes can be introduced to the JPlagReport and then processed in the report viewer. In the following example we add the number of tokens per match to the JPlag report and view. + +Task: Adding the number of tokens in a match, which has to be displayed in the MatchesTable in the ComparisonView. + +1. Add `int tokens` to `Match.java` (sub-model of `ComparisonReport.java`) +2. Modify the existing component `ComparisonReportWriter.java` to additionally extract the number of tokens in a match from the `JPlagResult.java` + and save it in the Match DTO +3. Add `tokens: number` to `Match.ts` +4. Edit `ComparisonFactory.ts` to get the number of tokens from the JSON report file. [report-viewer] +5. Edit `MatchTable.vue` to display the tokens number in the `ComparisonView.vue`. diff --git a/docs/7.-Clustering-of-Submissions.md b/docs/7.-Clustering-of-Submissions.md new file mode 100644 index 000000000..be1aee66a --- /dev/null +++ b/docs/7.-Clustering-of-Submissions.md @@ -0,0 +1,91 @@ +## Clustering Usage + +By default, JPlag is configured to perform a clustering of the submissions. +The clustering partitions the set of submissions into groups of similar submissions. +The found clusters can be used candidates for _potentially_ colluding groups. Each cluster has a strength score, that measures how _suspicious_ the cluster is compared to other clusters. + +### Disabling Clustering + +Clustering can take a long when there is a large number of submissions. +Users who are not interested in clustering can safely disable it with the `--cluster-skip` option. + +### Clustering Configuration + +Clustering can either be configured using the CLI options or programmatically using the `ClusteringOptions` class. Both options work analogously and share the same default values. + +__The clustering is designed to work out-of-the-box for running within the magnitude of about 50-500 submissions__, but it can be tweaked when problems occur. For more submissions it might be necessary to increase `Max-Runs` or `Bandwidth`, so that an appropriate number of clusters can be determined. + +| Group | Option | Description | Default | +| --- | --- | ----------- | - | +| General | Enable | Controls whether the clustering is run at all. | `true` | +| General | Algorithm | Which clustering algorithm to use.
Agglomerative Clustering
Agglomerative Clustering iteratively merges similar submissions bottom up. It usually requires manual tuning for its parameters to yield helpful clusters.
Spectral Clustering
Spectral Clustering is combined with Bayesian Optimization to execute the k-Means clustering algorithm multiple times, hopefully finding a \"good\" clustering automatically. Its default parameters should work O.K. in most cases.
| Agglomerative Clustering | +| General | Metric | The similarity score between submissions to use during clustering. Each score is expressed in terms of the size of the submissions `A` and `B` and the size of their matched intersection `A โˆฉ B`.
AVG (aka. Dice's coefficient)
`AVG = 2 * (A โˆฉ B) / (A + B)`
MAX (aka. overlap coefficient)
`MAX = (A โˆฉ B) / min(A, B)` Compared to MAX, this prevents obfuscation when a collaborator bloats his submission with unrelated code.
MIN (_deprecated_)
`MIN = (A โˆฉ B) / max(A, B)`
INTERSECTION (_experimental_)
`INTERSECTION = A โˆฉ B`
| AVG | +| Spectral | Bandwidth | For Spectral Clustering, Baysian Optimization is used to determine a fitting number of clusters. If a good clustering result is found during the search, numbers of clusters that differ by something in range of the bandwidth are also expected to good. Low values result in more exploration of the search space, high values in more exploitation of known results. | 20.0 | +| Spectral | Noise | The result of each k-Means run in the search for good clusterings is random. The noise level models the variance in the \"worth\" of these results. It also acts as a regularization constant. | 0.0025 | +| Spectral | Min-Runs | Minimum number of k-Means executions for spectral clustering. With these initial runs clustering sizes are explored. | 5 | +| Spectral | Max-Runs | Maximum number of k-Means executions during spectral clustering. Any execution after the initial (min-) runs tries to balance between exploration of unknown clustering sizes and exploitation of clustering sizes known as good. | 50 | +| Spectral | K-Means Iterations | Maximum number of iterations during each execution of the k-Means algorithm. | 200 | +| Agglomerative | Threshold | Only clusters with an inter-cluster-similarity greater than this threshold are merged during agglomerative clustering. | 0.2 | +| Agglomerative | inter-cluster-similarity | How to measure the similarity of two clusters during agglomerative clustering.
MIN (aka. complete-linkage)
Clusters are merged if all their submissions are similar.
MAX (aka. single-linkage)
Clusters are merged if there is a similar submission in both.
AVERAGE (aka. average-linkage)
Clusters are merged if their submissions are similar on average.
| AVERAGE | +| Preprocessing | Pre-Processor | How the similarities are preprocessed prior to clustering. Spectral Clustering will probably not have good results without it.
None
No preprocessing.
Cumulative Distribution Function (CDF)
Before clustering, the value of the cumulative distribution function of all similarities is estimated. The similarities are multiplied with these estimates. This has the effect of suppressing similarities that are low compared to other similarities.
Percentile
Any similarity smaller than the given percentile will be suppressed during clustering.
Threshold
Any similarity smaller than the given threshold will be suppressed during clustering.
| CDF | + +## Clustering Architecture + +All clustering related classes are contained within the `de.jplag.clustering(.*)` packages in the core project. + +The central idea behind the structure of clustering is the ease of use: To use the clustering calling code should only ever interact with the `ClusteringOptions`, `ClusteringFactory`, and `ClusteringResult` classes: + +```mermaid + +classDiagram + ClusteringFactory <.. CallingCode + ClusteringOptions <.. CallingCode : creates + ClusteringAdapter <.. ClusteringFactory + ClusteringAlgorithm <.. ClusteringAdapter : runs + ClusteringAlgorithm <.. ClusteringFactory : creates instances + ClusteringPreprocessor <.. ClusteringFactory : creates instances + PreprocessedClusteringAlgorithm <.. ClusteringFactory : creates + ClusteringOptions <-- ClusteringFactory + ClusteringAlgorithm <|-- PreprocessedClusteringAlgorithm + ClusteringAlgorithm <-- PreprocessedClusteringAlgorithm : delegates to + ClusteringPreprocessor ..o PreprocessedClusteringAlgorithm + class ClusteringFactory{ + getClusterings(List~JPlagComparison~ comparisons, ClusteringOptions options)$ ClusteringResult~Submission~ + } + class ClusteringOptions{ + } + class ClusteringAlgorithm { + <> + cluster(Matrix similarities) ClusteringResult~Integer~ + } + class ClusteringPreprocessor { + <> + preprocess(Matrix similarities) Matrix + } + class ClusteringAdapter{ + ClusteringAdapter(List~JplagComparison~ comparisons) + doClustering(ClusteringAlgorithm algorithm) ClusteringResult~Submission~ + } + class PreprocessedClusteringAlgorithm{ + cluster(Matrix similarities) ClusteringResult~Integer~ + } + class CallingCode{ + + } + +``` + +New clustering algorithms and preprocessors can be implemented using the `GenericClusteringAlgorithm` and `ClusteringPreprocessor` interfaces which operate on similarity matrices only. `ClusteringAdapter` handles the conversion between `de.jplag` classes and matrices. `PreprocessedClusteringAlgorithm` adds a preprocessor onto another `ClusteringAlgorithm`. +### Remarks on Spectral Clustering + +* based on [On Spectral Clustering: Analysis and an algorithm (Ng, Jordan & Weiss, 2001)](https://proceedings.neurips.cc/paper/2001/file/801272ee79cfde7fa5960571fee36b9b-Paper.pdf) +* automatic hyper-parameter search using Bayesian Optimization with a Gaussian Process as the surrogate model and L-BFGS for optimization on the surrogate +* the L-BFGS implementation is a pit of technical debt, [see here](https://github.com/jplag/JPlag/pull/281#discussion_r810171986). + + +### Integration Tests + +There are integration tests for the Spectral Clustering to verify, that a least in the case of two known sets of similarities the groups known to be colluders are found. However, these are considered to be sensitive data. The datasets are not available to the public and these tests can only be run by maintainers with access. + +To run these tests the contents of the [PseudonymizedReports](https://github.com/jplag/PseudonymizedReports) repository must added in the folder `jplag/src/test/resources/de/jplag/PseudonymizedReports`. + diff --git a/docs/Home.md b/docs/Home.md new file mode 100644 index 000000000..e7e2cbd2c --- /dev/null +++ b/docs/Home.md @@ -0,0 +1,40 @@ +

+ JPlag logo +

+ +## What is JPlag +JPlag is a system that finds similarities among multiple sets of source code files. This way it can detect software plagiarism and collusion in software development. JPlag does not merely compare bytes of text but is aware of programming language syntax and program structure and hence is robust against many kinds of attempts to disguise similarities between plagiarized files. JPlag currently supports Java, C#, C/C++, Python 3, Go, Rust, Kotlin, Swift, Scala, Scheme, EMF, and natural language text. + +JPlag is typically used to detect and thus discourage the unallowed copying of student exercise programs in programming education. But in principle, it can also be used to detect stolen software parts among large amounts of source text or modules that have been duplicated (and only slightly modified). JPlag has already played a part in several intellectual property cases where it has been successfully used by expert witnesses. + +[TODO]: <> (Link or visualize example report) + +**Just to make it clear**: JPlag does not compare to the internet! It is designed to find similarities among the student solutions, which is usually sufficient for computer programs. + +## History +Originally, JPlag was developed in 1996 by Guido Mahlpohl and others at the chair of Prof. Walter Tichy at Karlsruhe Institute of Technology (KIT). It was first documented in a [Tech Report](https://publikationen.bibliothek.kit.edu/542000) in 2000 and later more formally in the [Journal of Universal Computer Science](http://www.ipd.kit.edu/tichy/uploads/publikationen/16/finding_plagiarisms_among_a_set_of_progr_638847.pdf). Since 2015 JPlag is hosted here on GitHub. After 25 years of its creation, JPlag is still used frequently in many universities in different countries around the world. + +## Download JPlag +Download the latest version of JPlag [here](https://github.com/jplag/jplag/releases). If you encounter bugs or other issues, please report them [here](https://github.com/jplag/jplag/issues). + +## Using JPlag +Use JPlag via the CLI to analyze your set of source codes. You can display your results via [jplag.github.io](https://jplag.github.io/JPlag/). No data will leave your computer! More usage information can be found [here](https://github.com/jplag/JPlag/wiki/1.-How-to-Use-JPlag). + +## Include JPlag as a Dependency +JPlag is released on [Maven Central](https://search.maven.org/search?q=de.jplag), it can be included as follows: +```xml + + de.jplag + jplag + +``` + +## JPlag legacy version +In case you depend on the legacy version of JPlag we refer to the [legacy release v2.12.1](https://github.com/jplag/jplag/releases/tag/v2.12.1-SNAPSHOT) and the [legacy branch](https://github.com/jplag/jplag/tree/legacy). Note that the legacy CLI usage is slightly different. + +The following features are only available in version v4.0.0 and onwards: +* a modern web-based UI +* a simplified command-line interface +* support for Kotlin, Scala, Go, Rust, and R +* support for Java 17 language features +* a Java API for third-party integration diff --git a/endtoend-testing/src/test/java/de/jplag/endtoend/EndToEndGeneratorTest.java b/endtoend-testing/src/test/java/de/jplag/endtoend/EndToEndGeneratorTest.java index 45d7ffde0..2e8c4f0df 100644 --- a/endtoend-testing/src/test/java/de/jplag/endtoend/EndToEndGeneratorTest.java +++ b/endtoend-testing/src/test/java/de/jplag/endtoend/EndToEndGeneratorTest.java @@ -48,9 +48,9 @@ void generateResultJson() throws ExitException, IOException { File submissionDirectory = TestSuiteHelper.getSubmissionDirectory(language, TEST_SUITE_IDENTIFIER); List resultDescriptions = new ArrayList<>(); for (var option : OPTIONS) { - JPlagOptions jplagOptions = new JPlagOptions(language, Set.of(submissionDirectory), Set.of()) + JPlagOptions options = new JPlagOptions(language, Set.of(submissionDirectory), Set.of()) .withMinimumTokenMatch(option.minimumTokenMatch()); - JPlagResult jplagResult = new JPlag(jplagOptions).run(); + JPlagResult jplagResult = JPlag.run(options); List jPlagComparisons = jplagResult.getAllComparisons(); Map expectedResults = jPlagComparisons.stream() .collect(Collectors.toMap(TestSuiteHelper::getTestIdentifier, comparison -> new ExpectedResult(comparison.minimalSimilarity(), diff --git a/endtoend-testing/src/test/java/de/jplag/endtoend/EndToEndSuiteTest.java b/endtoend-testing/src/test/java/de/jplag/endtoend/EndToEndSuiteTest.java index 5be1d1a42..c5ffa4cb3 100644 --- a/endtoend-testing/src/test/java/de/jplag/endtoend/EndToEndSuiteTest.java +++ b/endtoend-testing/src/test/java/de/jplag/endtoend/EndToEndSuiteTest.java @@ -100,9 +100,9 @@ private DynamicContainer generateTestsForDataSet(Language language, File resultJ private Collection generateTestsForResultDescription(File resultJson, ResultDescription result, Language language) throws ExitException { File submissionDirectory = TestSuiteHelper.getSubmissionDirectory(language, resultJson); - JPlagOptions jplagOptions = new JPlagOptions(language, Set.of(submissionDirectory), Set.of()) + JPlagOptions options = new JPlagOptions(language, Set.of(submissionDirectory), Set.of()) .withMinimumTokenMatch(result.options().minimumTokenMatch()); - JPlagResult jplagResult = new JPlag(jplagOptions).run(); + JPlagResult jplagResult = JPlag.run(options); var comparisons = jplagResult.getAllComparisons().stream().collect(Collectors.toMap(it -> TestSuiteHelper.getTestIdentifier(it), it -> it)); assertEquals(result.identifierToResultMap().size(), comparisons.size(), "different number of results and expected results"); diff --git a/endtoend-testing/src/test/resources/results/java/sortAlgo.json b/endtoend-testing/src/test/resources/results/java/sortAlgo.json index 80fab2e72..70c8ebbbc 100644 --- a/endtoend-testing/src/test/resources/results/java/sortAlgo.json +++ b/endtoend-testing/src/test/resources/results/java/sortAlgo.json @@ -4,12 +4,12 @@ }, "tests" : { "SortAlgo-SortAlgo5" : { - "minimal_similarity" : 0.6046511627906976, - "maximum_similarity" : 0.6341463414634146, - "matched_token_number" : 26 + "minimal_similarity" : 0.6511627906976745, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 28 }, "SortAlgo-SortAlgo6" : { - "minimal_similarity" : 0.625, + "minimal_similarity" : 0.6122448979591837, "maximum_similarity" : 0.7317073170731707, "matched_token_number" : 30 }, @@ -19,13 +19,13 @@ "matched_token_number" : 38 }, "SortAlgo3_5-SortAlgo3_6" : { - "minimal_similarity" : 0.6428571428571429, - "maximum_similarity" : 0.6545454545454545, - "matched_token_number" : 36 + "minimal_similarity" : 0.7142857142857143, + "maximum_similarity" : 0.7142857142857143, + "matched_token_number" : 40 }, "SortAlgo6-SortAlgo7" : { "minimal_similarity" : 0.44642857142857145, - "maximum_similarity" : 0.5208333333333334, + "maximum_similarity" : 0.5102040816326531, "matched_token_number" : 25 }, "SortAlgo1_3-SortAlgo7" : { @@ -34,9 +34,9 @@ "matched_token_number" : 31 }, "SortAlgo1_3-SortAlgo6" : { - "minimal_similarity" : 0.6206896551724138, - "maximum_similarity" : 0.75, - "matched_token_number" : 36 + "minimal_similarity" : 0.6724137931034483, + "maximum_similarity" : 0.7959183673469388, + "matched_token_number" : 39 }, "SortAlgo-SortAlgo1" : { "minimal_similarity" : 1.0, @@ -64,24 +64,24 @@ "matched_token_number" : 33 }, "SortAlgo1_3-SortAlgo5" : { - "minimal_similarity" : 0.3620689655172414, - "maximum_similarity" : 0.4883720930232558, - "matched_token_number" : 21 + "minimal_similarity" : 0.4482758620689655, + "maximum_similarity" : 0.6046511627906976, + "matched_token_number" : 26 }, "SortAlgo-SortAlgo4" : { - "minimal_similarity" : 0.7380952380952381, - "maximum_similarity" : 0.7560975609756098, - "matched_token_number" : 31 + "minimal_similarity" : 0.7906976744186046, + "maximum_similarity" : 0.8292682926829268, + "matched_token_number" : 34 }, "SortAlgo1_3-SortAlgo4" : { - "minimal_similarity" : 0.46551724137931033, - "maximum_similarity" : 0.6428571428571429, - "matched_token_number" : 27 + "minimal_similarity" : 0.5172413793103449, + "maximum_similarity" : 0.6976744186046512, + "matched_token_number" : 30 }, "SortAlgo2-SortAlgo2_5" : { - "minimal_similarity" : 0.6046511627906976, - "maximum_similarity" : 0.6341463414634146, - "matched_token_number" : 26 + "minimal_similarity" : 0.6511627906976745, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 28 }, "SortAlgo1_2-SortAlgo2" : { "minimal_similarity" : 0.7454545454545455, @@ -94,28 +94,28 @@ "matched_token_number" : 34 }, "SortAlgo5-SortAlgo6" : { - "minimal_similarity" : 0.4791666666666667, - "maximum_similarity" : 0.5348837209302325, - "matched_token_number" : 23 + "minimal_similarity" : 0.5510204081632653, + "maximum_similarity" : 0.627906976744186, + "matched_token_number" : 27 }, "SortAlgo1_2-SortAlgo4" : { - "minimal_similarity" : 0.6181818181818182, - "maximum_similarity" : 0.8095238095238095, - "matched_token_number" : 34 + "minimal_similarity" : 0.7272727272727273, + "maximum_similarity" : 0.9302325581395349, + "matched_token_number" : 40 }, "SortAlgo5-SortAlgo7" : { - "minimal_similarity" : 0.3392857142857143, - "maximum_similarity" : 0.4418604651162791, - "matched_token_number" : 19 + "minimal_similarity" : 0.375, + "maximum_similarity" : 0.4883720930232558, + "matched_token_number" : 21 }, "SortAlgo1_2-SortAlgo5" : { - "minimal_similarity" : 0.4727272727272727, - "maximum_similarity" : 0.6046511627906976, - "matched_token_number" : 26 + "minimal_similarity" : 0.5636363636363636, + "maximum_similarity" : 0.7209302325581395, + "matched_token_number" : 31 }, "SortAlgo1_2-SortAlgo6" : { "minimal_similarity" : 0.5454545454545454, - "maximum_similarity" : 0.625, + "maximum_similarity" : 0.6122448979591837, "matched_token_number" : 30 }, "SortAlgo1_2-SortAlgo7" : { @@ -124,44 +124,44 @@ "matched_token_number" : 44 }, "SortAlgo1-SortAlgo2_5" : { - "minimal_similarity" : 0.6046511627906976, - "maximum_similarity" : 0.6341463414634146, - "matched_token_number" : 26 + "minimal_similarity" : 0.6511627906976745, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 28 }, "SortAlgo1_3-SortAlgo3_6" : { "minimal_similarity" : 0.7758620689655172, - "maximum_similarity" : 0.8181818181818182, + "maximum_similarity" : 0.8035714285714286, "matched_token_number" : 45 }, "SortAlgo4-SortAlgo5" : { - "minimal_similarity" : 0.5813953488372093, - "maximum_similarity" : 0.5952380952380952, - "matched_token_number" : 25 + "minimal_similarity" : 0.627906976744186, + "maximum_similarity" : 0.627906976744186, + "matched_token_number" : 27 }, "SortAlgo4-SortAlgo6" : { - "minimal_similarity" : 0.4791666666666667, - "maximum_similarity" : 0.5476190476190477, - "matched_token_number" : 23 + "minimal_similarity" : 0.5306122448979592, + "maximum_similarity" : 0.6046511627906976, + "matched_token_number" : 26 }, "SortAlgo4-SortAlgo7" : { - "minimal_similarity" : 0.5357142857142857, - "maximum_similarity" : 0.7142857142857143, - "matched_token_number" : 30 + "minimal_similarity" : 0.5892857142857143, + "maximum_similarity" : 0.7674418604651163, + "matched_token_number" : 33 }, "SortAlgo1_4-SortAlgo3_5" : { - "minimal_similarity" : 0.35714285714285715, - "maximum_similarity" : 0.47619047619047616, - "matched_token_number" : 20 + "minimal_similarity" : 0.42857142857142855, + "maximum_similarity" : 0.5581395348837209, + "matched_token_number" : 24 }, "SortAlgo1_4-SortAlgo3_6" : { - "minimal_similarity" : 0.509090909090909, - "maximum_similarity" : 0.6666666666666666, - "matched_token_number" : 28 + "minimal_similarity" : 0.5535714285714286, + "maximum_similarity" : 0.7209302325581395, + "matched_token_number" : 31 }, "SortAlgo1_5-SortAlgo3_6" : { - "minimal_similarity" : 0.4, - "maximum_similarity" : 0.5116279069767442, - "matched_token_number" : 22 + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.6511627906976745, + "matched_token_number" : 28 }, "SortAlgo1_5-SortAlgo3_5" : { "minimal_similarity" : 0.6607142857142857, @@ -169,9 +169,9 @@ "matched_token_number" : 37 }, "SortAlgo1_6-SortAlgo3_5" : { - "minimal_similarity" : 0.39285714285714285, - "maximum_similarity" : 0.5238095238095238, - "matched_token_number" : 22 + "minimal_similarity" : 0.4642857142857143, + "maximum_similarity" : 0.6046511627906976, + "matched_token_number" : 26 }, "SortAlgo-SortAlgo4d3" : { "minimal_similarity" : 0.8297872340425532, @@ -179,9 +179,9 @@ "matched_token_number" : 39 }, "SortAlgo1_6-SortAlgo3_6" : { - "minimal_similarity" : 0.6181818181818182, - "maximum_similarity" : 0.8095238095238095, - "matched_token_number" : 34 + "minimal_similarity" : 0.625, + "maximum_similarity" : 0.813953488372093, + "matched_token_number" : 35 }, "SortAlgo-SortAlgo4d2" : { "minimal_similarity" : 0.7959183673469388, @@ -194,64 +194,64 @@ "matched_token_number" : 39 }, "SortAlgo1_4-SortAlgo3" : { - "minimal_similarity" : 0.5925925925925926, - "maximum_similarity" : 0.7619047619047619, - "matched_token_number" : 32 + "minimal_similarity" : 0.6481481481481481, + "maximum_similarity" : 0.813953488372093, + "matched_token_number" : 35 }, "SortAlgo3-SortAlgo3_5" : { - "minimal_similarity" : 0.6428571428571429, - "maximum_similarity" : 0.6666666666666666, - "matched_token_number" : 36 + "minimal_similarity" : 0.6785714285714286, + "maximum_similarity" : 0.7037037037037037, + "matched_token_number" : 38 }, "SortAlgo1_4-SortAlgo4" : { - "minimal_similarity" : 0.9523809523809523, - "maximum_similarity" : 0.9523809523809523, - "matched_token_number" : 40 + "minimal_similarity" : 0.9534883720930233, + "maximum_similarity" : 0.9534883720930233, + "matched_token_number" : 41 }, "SortAlgo3-SortAlgo3_6" : { - "minimal_similarity" : 0.9272727272727272, + "minimal_similarity" : 0.9107142857142857, "maximum_similarity" : 0.9444444444444444, "matched_token_number" : 51 }, "SortAlgo1_4-SortAlgo2" : { - "minimal_similarity" : 0.7857142857142857, - "maximum_similarity" : 0.8048780487804879, - "matched_token_number" : 33 + "minimal_similarity" : 0.8372093023255814, + "maximum_similarity" : 0.8780487804878049, + "matched_token_number" : 36 }, "SortAlgo1_4-SortAlgo7" : { - "minimal_similarity" : 0.5178571428571429, - "maximum_similarity" : 0.6904761904761905, - "matched_token_number" : 29 + "minimal_similarity" : 0.5714285714285714, + "maximum_similarity" : 0.7441860465116279, + "matched_token_number" : 32 }, "SortAlgo1_4-SortAlgo5" : { - "minimal_similarity" : 0.5348837209302325, - "maximum_similarity" : 0.5476190476190477, - "matched_token_number" : 23 + "minimal_similarity" : 0.6046511627906976, + "maximum_similarity" : 0.6046511627906976, + "matched_token_number" : 26 }, "SortAlgo2-SortAlgo3_5" : { - "minimal_similarity" : 0.375, - "maximum_similarity" : 0.5121951219512195, - "matched_token_number" : 21 + "minimal_similarity" : 0.4107142857142857, + "maximum_similarity" : 0.5609756097560976, + "matched_token_number" : 23 }, "SortAlgo1_4-SortAlgo6" : { - "minimal_similarity" : 0.6041666666666666, - "maximum_similarity" : 0.6904761904761905, - "matched_token_number" : 29 + "minimal_similarity" : 0.6530612244897959, + "maximum_similarity" : 0.7441860465116279, + "matched_token_number" : 32 }, "SortAlgo2-SortAlgo3_6" : { - "minimal_similarity" : 0.4727272727272727, + "minimal_similarity" : 0.4642857142857143, "maximum_similarity" : 0.6341463414634146, "matched_token_number" : 26 }, "SortAlgo1-SortAlgo3_6" : { - "minimal_similarity" : 0.4727272727272727, + "minimal_similarity" : 0.4642857142857143, "maximum_similarity" : 0.6341463414634146, "matched_token_number" : 26 }, "SortAlgo1-SortAlgo3_5" : { - "minimal_similarity" : 0.375, - "maximum_similarity" : 0.5121951219512195, - "matched_token_number" : 21 + "minimal_similarity" : 0.4107142857142857, + "maximum_similarity" : 0.5609756097560976, + "matched_token_number" : 23 }, "SortAlgo-SortAlgo1_2" : { "minimal_similarity" : 0.7454545454545455, @@ -259,34 +259,34 @@ "matched_token_number" : 41 }, "SortAlgo1_3-SortAlgo3_5" : { - "minimal_similarity" : 0.5172413793103449, - "maximum_similarity" : 0.5357142857142857, - "matched_token_number" : 30 + "minimal_similarity" : 0.603448275862069, + "maximum_similarity" : 0.625, + "matched_token_number" : 35 }, "SortAlgo1_2-SortAlgo3_5" : { - "minimal_similarity" : 0.375, - "maximum_similarity" : 0.38181818181818183, - "matched_token_number" : 21 + "minimal_similarity" : 0.4642857142857143, + "maximum_similarity" : 0.4727272727272727, + "matched_token_number" : 26 }, "SortAlgo1_2-SortAlgo3_6" : { - "minimal_similarity" : 0.5818181818181818, + "minimal_similarity" : 0.5714285714285714, "maximum_similarity" : 0.5818181818181818, "matched_token_number" : 32 }, "SortAlgo-SortAlgo1_6" : { - "minimal_similarity" : 0.8095238095238095, + "minimal_similarity" : 0.7906976744186046, "maximum_similarity" : 0.8292682926829268, "matched_token_number" : 34 }, "SortAlgo-SortAlgo1_5" : { - "minimal_similarity" : 0.6046511627906976, - "maximum_similarity" : 0.6341463414634146, - "matched_token_number" : 26 + "minimal_similarity" : 0.6511627906976745, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 28 }, "SortAlgo-SortAlgo1_4" : { - "minimal_similarity" : 0.7857142857142857, - "maximum_similarity" : 0.8048780487804879, - "matched_token_number" : 33 + "minimal_similarity" : 0.8372093023255814, + "maximum_similarity" : 0.8780487804878049, + "matched_token_number" : 36 }, "SortAlgo-SortAlgo1_3" : { "minimal_similarity" : 0.5689655172413793, @@ -294,9 +294,9 @@ "matched_token_number" : 33 }, "SortAlgo1_6-SortAlgo4d1" : { - "minimal_similarity" : 0.6458333333333334, - "maximum_similarity" : 0.7380952380952381, - "matched_token_number" : 31 + "minimal_similarity" : 0.7083333333333334, + "maximum_similarity" : 0.7906976744186046, + "matched_token_number" : 34 }, "SortAlgo4d2-SortAlgo7" : { "minimal_similarity" : 0.6428571428571429, @@ -304,24 +304,24 @@ "matched_token_number" : 36 }, "SortAlgo1_6-SortAlgo4d2" : { - "minimal_similarity" : 0.6326530612244898, - "maximum_similarity" : 0.7380952380952381, - "matched_token_number" : 31 + "minimal_similarity" : 0.6938775510204082, + "maximum_similarity" : 0.7906976744186046, + "matched_token_number" : 34 }, "SortAlgo4d2-SortAlgo5" : { - "minimal_similarity" : 0.4897959183673469, - "maximum_similarity" : 0.5581395348837209, - "matched_token_number" : 24 + "minimal_similarity" : 0.5306122448979592, + "maximum_similarity" : 0.6046511627906976, + "matched_token_number" : 26 }, "SortAlgo4d2-SortAlgo6" : { - "minimal_similarity" : 0.6326530612244898, - "maximum_similarity" : 0.6458333333333334, - "matched_token_number" : 31 + "minimal_similarity" : 0.6938775510204082, + "maximum_similarity" : 0.6938775510204082, + "matched_token_number" : 34 }, "SortAlgo1_6-SortAlgo4d3" : { - "minimal_similarity" : 0.6595744680851063, - "maximum_similarity" : 0.7380952380952381, - "matched_token_number" : 31 + "minimal_similarity" : 0.723404255319149, + "maximum_similarity" : 0.7906976744186046, + "matched_token_number" : 34 }, "SortAlgo1_5-SortAlgo2_5" : { "minimal_similarity" : 1.0, @@ -343,6 +343,11 @@ "maximum_similarity" : 0.8048780487804879, "matched_token_number" : 33 }, + "SortAlgo2-SortAlgo4" : { + "minimal_similarity" : 0.7906976744186046, + "maximum_similarity" : 0.8292682926829268, + "matched_token_number" : 34 + }, "SortAlgo1_2-SortAlgo4d2" : { "minimal_similarity" : 0.7090909090909091, "maximum_similarity" : 0.7959183673469388, @@ -353,45 +358,40 @@ "maximum_similarity" : 0.8163265306122449, "matched_token_number" : 40 }, - "SortAlgo2-SortAlgo4" : { - "minimal_similarity" : 0.7380952380952381, - "maximum_similarity" : 0.7560975609756098, - "matched_token_number" : 31 - }, "SortAlgo1_6-SortAlgo2_5" : { - "minimal_similarity" : 0.627906976744186, - "maximum_similarity" : 0.6428571428571429, - "matched_token_number" : 27 + "minimal_similarity" : 0.7209302325581395, + "maximum_similarity" : 0.7209302325581395, + "matched_token_number" : 31 }, "SortAlgo1_4-SortAlgo4d1" : { - "minimal_similarity" : 0.6458333333333334, - "maximum_similarity" : 0.7380952380952381, - "matched_token_number" : 31 + "minimal_similarity" : 0.7083333333333334, + "maximum_similarity" : 0.7906976744186046, + "matched_token_number" : 34 }, "SortAlgo1_5-SortAlgo4d3" : { - "minimal_similarity" : 0.5106382978723404, - "maximum_similarity" : 0.5581395348837209, - "matched_token_number" : 24 + "minimal_similarity" : 0.5531914893617021, + "maximum_similarity" : 0.6046511627906976, + "matched_token_number" : 26 }, "SortAlgo1_4-SortAlgo4d2" : { - "minimal_similarity" : 0.6326530612244898, - "maximum_similarity" : 0.7380952380952381, - "matched_token_number" : 31 + "minimal_similarity" : 0.6938775510204082, + "maximum_similarity" : 0.7906976744186046, + "matched_token_number" : 34 }, "SortAlgo1_5-SortAlgo4d2" : { - "minimal_similarity" : 0.4897959183673469, - "maximum_similarity" : 0.5581395348837209, - "matched_token_number" : 24 + "minimal_similarity" : 0.5306122448979592, + "maximum_similarity" : 0.6046511627906976, + "matched_token_number" : 26 }, "SortAlgo1_4-SortAlgo4d3" : { - "minimal_similarity" : 0.6595744680851063, - "maximum_similarity" : 0.7380952380952381, - "matched_token_number" : 31 + "minimal_similarity" : 0.723404255319149, + "maximum_similarity" : 0.7906976744186046, + "matched_token_number" : 34 }, "SortAlgo1_5-SortAlgo4d1" : { - "minimal_similarity" : 0.5, - "maximum_similarity" : 0.5581395348837209, - "matched_token_number" : 24 + "minimal_similarity" : 0.5416666666666666, + "maximum_similarity" : 0.6046511627906976, + "matched_token_number" : 26 }, "SortAlgo4d2-SortAlgo4d3" : { "minimal_similarity" : 0.9183673469387755, @@ -419,9 +419,9 @@ "matched_token_number" : 40 }, "SortAlgo2-SortAlgo5" : { - "minimal_similarity" : 0.6046511627906976, - "maximum_similarity" : 0.6341463414634146, - "matched_token_number" : 26 + "minimal_similarity" : 0.6511627906976745, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 28 }, "SortAlgo4d1-SortAlgo4d3" : { "minimal_similarity" : 0.9375, @@ -429,19 +429,19 @@ "matched_token_number" : 45 }, "SortAlgo2-SortAlgo6" : { - "minimal_similarity" : 0.625, + "minimal_similarity" : 0.6122448979591837, "maximum_similarity" : 0.7317073170731707, "matched_token_number" : 30 }, "SortAlgo1_6-SortAlgo7" : { "minimal_similarity" : 0.5, - "maximum_similarity" : 0.6666666666666666, + "maximum_similarity" : 0.6511627906976745, "matched_token_number" : 28 }, "SortAlgo3_6-SortAlgo6" : { - "minimal_similarity" : 0.8, - "maximum_similarity" : 0.9166666666666666, - "matched_token_number" : 44 + "minimal_similarity" : 0.8035714285714286, + "maximum_similarity" : 0.9183673469387755, + "matched_token_number" : 45 }, "SortAlgo2_5-SortAlgo3_5" : { "minimal_similarity" : 0.6607142857142857, @@ -449,24 +449,24 @@ "matched_token_number" : 37 }, "SortAlgo3_6-SortAlgo5" : { - "minimal_similarity" : 0.4, - "maximum_similarity" : 0.5116279069767442, - "matched_token_number" : 22 + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.6511627906976745, + "matched_token_number" : 28 }, "SortAlgo2_5-SortAlgo3_6" : { - "minimal_similarity" : 0.4, - "maximum_similarity" : 0.5116279069767442, - "matched_token_number" : 22 + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.6511627906976745, + "matched_token_number" : 28 }, "SortAlgo3_6-SortAlgo7" : { "minimal_similarity" : 0.42857142857142855, - "maximum_similarity" : 0.43636363636363634, + "maximum_similarity" : 0.42857142857142855, "matched_token_number" : 24 }, "SortAlgo4d3-SortAlgo6" : { - "minimal_similarity" : 0.6458333333333334, - "maximum_similarity" : 0.6595744680851063, - "matched_token_number" : 31 + "minimal_similarity" : 0.6938775510204082, + "maximum_similarity" : 0.723404255319149, + "matched_token_number" : 34 }, "SortAlgo4d3-SortAlgo7" : { "minimal_similarity" : 0.6428571428571429, @@ -474,24 +474,24 @@ "matched_token_number" : 36 }, "SortAlgo4d3-SortAlgo5" : { - "minimal_similarity" : 0.5106382978723404, - "maximum_similarity" : 0.5581395348837209, - "matched_token_number" : 24 + "minimal_similarity" : 0.5531914893617021, + "maximum_similarity" : 0.6046511627906976, + "matched_token_number" : 26 }, "SortAlgo1_4-SortAlgo2_5" : { - "minimal_similarity" : 0.5348837209302325, - "maximum_similarity" : 0.5476190476190477, - "matched_token_number" : 23 + "minimal_similarity" : 0.6046511627906976, + "maximum_similarity" : 0.6046511627906976, + "matched_token_number" : 26 }, "SortAlgo1-SortAlgo4" : { - "minimal_similarity" : 0.7380952380952381, - "maximum_similarity" : 0.7560975609756098, - "matched_token_number" : 31 + "minimal_similarity" : 0.7906976744186046, + "maximum_similarity" : 0.8292682926829268, + "matched_token_number" : 34 }, "SortAlgo1-SortAlgo5" : { - "minimal_similarity" : 0.6046511627906976, - "maximum_similarity" : 0.6341463414634146, - "matched_token_number" : 26 + "minimal_similarity" : 0.6511627906976745, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 28 }, "SortAlgo1-SortAlgo2" : { "minimal_similarity" : 1.0, @@ -499,9 +499,9 @@ "matched_token_number" : 41 }, "SortAlgo3_6-SortAlgo4" : { - "minimal_similarity" : 0.45454545454545453, - "maximum_similarity" : 0.5952380952380952, - "matched_token_number" : 25 + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.6511627906976745, + "matched_token_number" : 28 }, "SortAlgo1-SortAlgo3" : { "minimal_similarity" : 0.6111111111111112, @@ -509,17 +509,17 @@ "matched_token_number" : 33 }, "SortAlgo1_3-SortAlgo2_5" : { - "minimal_similarity" : 0.3620689655172414, - "maximum_similarity" : 0.4883720930232558, - "matched_token_number" : 21 + "minimal_similarity" : 0.4482758620689655, + "maximum_similarity" : 0.6046511627906976, + "matched_token_number" : 26 }, "SortAlgo1_6-SortAlgo2" : { - "minimal_similarity" : 0.8095238095238095, + "minimal_similarity" : 0.7906976744186046, "maximum_similarity" : 0.8292682926829268, "matched_token_number" : 34 }, "SortAlgo1-SortAlgo6" : { - "minimal_similarity" : 0.625, + "minimal_similarity" : 0.6122448979591837, "maximum_similarity" : 0.7317073170731707, "matched_token_number" : 30 }, @@ -529,49 +529,49 @@ "matched_token_number" : 38 }, "SortAlgo1_2-SortAlgo2_5" : { - "minimal_similarity" : 0.4727272727272727, - "maximum_similarity" : 0.6046511627906976, - "matched_token_number" : 26 + "minimal_similarity" : 0.5636363636363636, + "maximum_similarity" : 0.7209302325581395, + "matched_token_number" : 31 }, "SortAlgo1_6-SortAlgo6" : { - "minimal_similarity" : 0.7916666666666666, - "maximum_similarity" : 0.9047619047619048, - "matched_token_number" : 38 + "minimal_similarity" : 0.7959183673469388, + "maximum_similarity" : 0.9069767441860465, + "matched_token_number" : 39 }, "SortAlgo-SortAlgo2_5" : { - "minimal_similarity" : 0.6046511627906976, - "maximum_similarity" : 0.6341463414634146, - "matched_token_number" : 26 + "minimal_similarity" : 0.6511627906976745, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 28 }, "SortAlgo1_6-SortAlgo5" : { - "minimal_similarity" : 0.627906976744186, - "maximum_similarity" : 0.6428571428571429, - "matched_token_number" : 27 + "minimal_similarity" : 0.7209302325581395, + "maximum_similarity" : 0.7209302325581395, + "matched_token_number" : 31 }, "SortAlgo1_6-SortAlgo4" : { - "minimal_similarity" : 0.6428571428571429, - "maximum_similarity" : 0.6428571428571429, - "matched_token_number" : 27 + "minimal_similarity" : 0.6976744186046512, + "maximum_similarity" : 0.6976744186046512, + "matched_token_number" : 30 }, "SortAlgo1_6-SortAlgo3" : { - "minimal_similarity" : 0.48148148148148145, - "maximum_similarity" : 0.6190476190476191, - "matched_token_number" : 26 + "minimal_similarity" : 0.5370370370370371, + "maximum_similarity" : 0.6744186046511628, + "matched_token_number" : 29 }, "SortAlgo1_5-SortAlgo6" : { - "minimal_similarity" : 0.4791666666666667, - "maximum_similarity" : 0.5348837209302325, - "matched_token_number" : 23 + "minimal_similarity" : 0.5510204081632653, + "maximum_similarity" : 0.627906976744186, + "matched_token_number" : 27 }, "SortAlgo2_5-SortAlgo7" : { - "minimal_similarity" : 0.3392857142857143, - "maximum_similarity" : 0.4418604651162791, - "matched_token_number" : 19 + "minimal_similarity" : 0.375, + "maximum_similarity" : 0.4883720930232558, + "matched_token_number" : 21 }, "SortAlgo1_5-SortAlgo7" : { - "minimal_similarity" : 0.3392857142857143, - "maximum_similarity" : 0.4418604651162791, - "matched_token_number" : 19 + "minimal_similarity" : 0.375, + "maximum_similarity" : 0.4883720930232558, + "matched_token_number" : 21 }, "SortAlgo1-SortAlgo4d3" : { "minimal_similarity" : 0.8297872340425532, @@ -579,9 +579,9 @@ "matched_token_number" : 39 }, "SortAlgo1_5-SortAlgo4" : { - "minimal_similarity" : 0.5813953488372093, - "maximum_similarity" : 0.5952380952380952, - "matched_token_number" : 25 + "minimal_similarity" : 0.627906976744186, + "maximum_similarity" : 0.627906976744186, + "matched_token_number" : 27 }, "SortAlgo1_5-SortAlgo5" : { "minimal_similarity" : 1.0, @@ -598,25 +598,25 @@ "maximum_similarity" : 0.9512195121951219, "matched_token_number" : 39 }, - "SortAlgo1_5-SortAlgo2" : { - "minimal_similarity" : 0.6046511627906976, - "maximum_similarity" : 0.6341463414634146, - "matched_token_number" : 26 - }, "SortAlgo3_5-SortAlgo6" : { - "minimal_similarity" : 0.5714285714285714, - "maximum_similarity" : 0.6666666666666666, - "matched_token_number" : 32 + "minimal_similarity" : 0.6428571428571429, + "maximum_similarity" : 0.7346938775510204, + "matched_token_number" : 36 + }, + "SortAlgo1_5-SortAlgo2" : { + "minimal_similarity" : 0.6511627906976745, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 28 }, "SortAlgo1_5-SortAlgo3" : { - "minimal_similarity" : 0.3888888888888889, - "maximum_similarity" : 0.4883720930232558, - "matched_token_number" : 21 + "minimal_similarity" : 0.46296296296296297, + "maximum_similarity" : 0.5813953488372093, + "matched_token_number" : 25 }, "SortAlgo3_5-SortAlgo7" : { - "minimal_similarity" : 0.26785714285714285, - "maximum_similarity" : 0.26785714285714285, - "matched_token_number" : 15 + "minimal_similarity" : 0.30357142857142855, + "maximum_similarity" : 0.30357142857142855, + "matched_token_number" : 17 }, "SortAlgo3-SortAlgo4d1" : { "minimal_similarity" : 0.7407407407407407, @@ -649,9 +649,9 @@ "matched_token_number" : 39 }, "SortAlgo1_5-SortAlgo1_6" : { - "minimal_similarity" : 0.627906976744186, - "maximum_similarity" : 0.6428571428571429, - "matched_token_number" : 27 + "minimal_similarity" : 0.7209302325581395, + "maximum_similarity" : 0.7209302325581395, + "matched_token_number" : 31 }, "SortAlgo4d1-SortAlgo7" : { "minimal_similarity" : 0.6428571428571429, @@ -659,54 +659,54 @@ "matched_token_number" : 36 }, "SortAlgo3_6-SortAlgo4d2" : { - "minimal_similarity" : 0.5818181818181818, - "maximum_similarity" : 0.6530612244897959, - "matched_token_number" : 32 + "minimal_similarity" : 0.625, + "maximum_similarity" : 0.7142857142857143, + "matched_token_number" : 35 }, "SortAlgo4d1-SortAlgo6" : { - "minimal_similarity" : 0.6458333333333334, - "maximum_similarity" : 0.6458333333333334, - "matched_token_number" : 31 + "minimal_similarity" : 0.6938775510204082, + "maximum_similarity" : 0.7083333333333334, + "matched_token_number" : 34 }, "SortAlgo3_6-SortAlgo4d1" : { - "minimal_similarity" : 0.5818181818181818, - "maximum_similarity" : 0.6666666666666666, - "matched_token_number" : 32 + "minimal_similarity" : 0.625, + "maximum_similarity" : 0.7291666666666666, + "matched_token_number" : 35 }, "SortAlgo4-SortAlgo4d1" : { - "minimal_similarity" : 0.5208333333333334, - "maximum_similarity" : 0.5952380952380952, - "matched_token_number" : 25 + "minimal_similarity" : 0.5833333333333334, + "maximum_similarity" : 0.6511627906976745, + "matched_token_number" : 28 }, "SortAlgo3_6-SortAlgo4d3" : { - "minimal_similarity" : 0.5818181818181818, - "maximum_similarity" : 0.6808510638297872, - "matched_token_number" : 32 + "minimal_similarity" : 0.625, + "maximum_similarity" : 0.7446808510638298, + "matched_token_number" : 35 }, "SortAlgo4-SortAlgo4d2" : { - "minimal_similarity" : 0.5102040816326531, - "maximum_similarity" : 0.5952380952380952, - "matched_token_number" : 25 + "minimal_similarity" : 0.5714285714285714, + "maximum_similarity" : 0.6511627906976745, + "matched_token_number" : 28 }, "SortAlgo4-SortAlgo4d3" : { - "minimal_similarity" : 0.5319148936170213, - "maximum_similarity" : 0.5952380952380952, - "matched_token_number" : 25 + "minimal_similarity" : 0.5957446808510638, + "maximum_similarity" : 0.6511627906976745, + "matched_token_number" : 28 }, "SortAlgo4d1-SortAlgo5" : { - "minimal_similarity" : 0.5, - "maximum_similarity" : 0.5581395348837209, - "matched_token_number" : 24 + "minimal_similarity" : 0.5416666666666666, + "maximum_similarity" : 0.6046511627906976, + "matched_token_number" : 26 }, "SortAlgo3_5-SortAlgo4d2" : { - "minimal_similarity" : 0.4107142857142857, - "maximum_similarity" : 0.46938775510204084, - "matched_token_number" : 23 + "minimal_similarity" : 0.44642857142857145, + "maximum_similarity" : 0.5102040816326531, + "matched_token_number" : 25 }, "SortAlgo3_5-SortAlgo4" : { - "minimal_similarity" : 0.30357142857142855, - "maximum_similarity" : 0.40476190476190477, - "matched_token_number" : 17 + "minimal_similarity" : 0.35714285714285715, + "maximum_similarity" : 0.46511627906976744, + "matched_token_number" : 20 }, "SortAlgo3_5-SortAlgo5" : { "minimal_similarity" : 0.6607142857142857, @@ -714,29 +714,29 @@ "matched_token_number" : 37 }, "SortAlgo3_5-SortAlgo4d3" : { - "minimal_similarity" : 0.4107142857142857, - "maximum_similarity" : 0.48936170212765956, - "matched_token_number" : 23 + "minimal_similarity" : 0.44642857142857145, + "maximum_similarity" : 0.5319148936170213, + "matched_token_number" : 25 }, "SortAlgo2_5-SortAlgo4" : { - "minimal_similarity" : 0.5813953488372093, - "maximum_similarity" : 0.5952380952380952, + "minimal_similarity" : 0.627906976744186, + "maximum_similarity" : 0.627906976744186, + "matched_token_number" : 27 + }, + "SortAlgo2_5-SortAlgo3" : { + "minimal_similarity" : 0.46296296296296297, + "maximum_similarity" : 0.5813953488372093, "matched_token_number" : 25 }, "SortAlgo3_5-SortAlgo4d1" : { - "minimal_similarity" : 0.4107142857142857, - "maximum_similarity" : 0.4791666666666667, - "matched_token_number" : 23 - }, - "SortAlgo2_5-SortAlgo3" : { - "minimal_similarity" : 0.3888888888888889, - "maximum_similarity" : 0.4883720930232558, - "matched_token_number" : 21 + "minimal_similarity" : 0.44642857142857145, + "maximum_similarity" : 0.5208333333333334, + "matched_token_number" : 25 }, "SortAlgo2_5-SortAlgo6" : { - "minimal_similarity" : 0.4791666666666667, - "maximum_similarity" : 0.5348837209302325, - "matched_token_number" : 23 + "minimal_similarity" : 0.5510204081632653, + "maximum_similarity" : 0.627906976744186, + "matched_token_number" : 27 }, "SortAlgo2_5-SortAlgo5" : { "minimal_similarity" : 1.0, @@ -754,99 +754,99 @@ "matched_token_number" : 41 }, "SortAlgo1-SortAlgo1_6" : { - "minimal_similarity" : 0.8095238095238095, + "minimal_similarity" : 0.7906976744186046, "maximum_similarity" : 0.8292682926829268, "matched_token_number" : 34 }, "SortAlgo1-SortAlgo1_5" : { - "minimal_similarity" : 0.6046511627906976, - "maximum_similarity" : 0.6341463414634146, - "matched_token_number" : 26 + "minimal_similarity" : 0.6511627906976745, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 28 }, "SortAlgo1-SortAlgo1_4" : { - "minimal_similarity" : 0.7857142857142857, - "maximum_similarity" : 0.8048780487804879, - "matched_token_number" : 33 + "minimal_similarity" : 0.8372093023255814, + "maximum_similarity" : 0.8780487804878049, + "matched_token_number" : 36 + }, + "SortAlgo2_5-SortAlgo4d1" : { + "minimal_similarity" : 0.5416666666666666, + "maximum_similarity" : 0.6046511627906976, + "matched_token_number" : 26 }, "SortAlgo3-SortAlgo7" : { "minimal_similarity" : 0.5535714285714286, "maximum_similarity" : 0.5740740740740741, "matched_token_number" : 31 }, - "SortAlgo2_5-SortAlgo4d1" : { - "minimal_similarity" : 0.5, - "maximum_similarity" : 0.5581395348837209, - "matched_token_number" : 24 - }, "SortAlgo3-SortAlgo6" : { - "minimal_similarity" : 0.6666666666666666, - "maximum_similarity" : 0.75, - "matched_token_number" : 36 + "minimal_similarity" : 0.7222222222222222, + "maximum_similarity" : 0.7959183673469388, + "matched_token_number" : 39 }, "SortAlgo2_5-SortAlgo4d2" : { - "minimal_similarity" : 0.4897959183673469, - "maximum_similarity" : 0.5581395348837209, - "matched_token_number" : 24 + "minimal_similarity" : 0.5306122448979592, + "maximum_similarity" : 0.6046511627906976, + "matched_token_number" : 26 }, "SortAlgo1_4-SortAlgo1_5" : { - "minimal_similarity" : 0.5348837209302325, - "maximum_similarity" : 0.5476190476190477, - "matched_token_number" : 23 + "minimal_similarity" : 0.6046511627906976, + "maximum_similarity" : 0.6046511627906976, + "matched_token_number" : 26 }, "SortAlgo3-SortAlgo5" : { - "minimal_similarity" : 0.3888888888888889, - "maximum_similarity" : 0.4883720930232558, - "matched_token_number" : 21 + "minimal_similarity" : 0.46296296296296297, + "maximum_similarity" : 0.5813953488372093, + "matched_token_number" : 25 }, "SortAlgo1_4-SortAlgo1_6" : { - "minimal_similarity" : 0.6904761904761905, - "maximum_similarity" : 0.6904761904761905, - "matched_token_number" : 29 + "minimal_similarity" : 0.7441860465116279, + "maximum_similarity" : 0.7441860465116279, + "matched_token_number" : 32 }, "SortAlgo3-SortAlgo4" : { - "minimal_similarity" : 0.48148148148148145, - "maximum_similarity" : 0.6190476190476191, - "matched_token_number" : 26 + "minimal_similarity" : 0.5370370370370371, + "maximum_similarity" : 0.6744186046511628, + "matched_token_number" : 29 }, "SortAlgo1_3-SortAlgo1_5" : { - "minimal_similarity" : 0.3620689655172414, - "maximum_similarity" : 0.4883720930232558, - "matched_token_number" : 21 + "minimal_similarity" : 0.4482758620689655, + "maximum_similarity" : 0.6046511627906976, + "matched_token_number" : 26 }, "SortAlgo1_3-SortAlgo1_4" : { - "minimal_similarity" : 0.5172413793103449, - "maximum_similarity" : 0.7142857142857143, - "matched_token_number" : 30 + "minimal_similarity" : 0.5689655172413793, + "maximum_similarity" : 0.7674418604651163, + "matched_token_number" : 33 }, "SortAlgo2_5-SortAlgo4d3" : { - "minimal_similarity" : 0.5106382978723404, - "maximum_similarity" : 0.5581395348837209, - "matched_token_number" : 24 + "minimal_similarity" : 0.5531914893617021, + "maximum_similarity" : 0.6046511627906976, + "matched_token_number" : 26 }, "SortAlgo1_3-SortAlgo1_6" : { - "minimal_similarity" : 0.4827586206896552, - "maximum_similarity" : 0.6666666666666666, - "matched_token_number" : 28 + "minimal_similarity" : 0.5344827586206896, + "maximum_similarity" : 0.7209302325581395, + "matched_token_number" : 31 + }, + "SortAlgo1_2-SortAlgo1_5" : { + "minimal_similarity" : 0.5636363636363636, + "maximum_similarity" : 0.7209302325581395, + "matched_token_number" : 31 }, "SortAlgo-SortAlgo3_6" : { - "minimal_similarity" : 0.4727272727272727, + "minimal_similarity" : 0.4642857142857143, "maximum_similarity" : 0.6341463414634146, "matched_token_number" : 26 }, - "SortAlgo1_2-SortAlgo1_5" : { - "minimal_similarity" : 0.4727272727272727, - "maximum_similarity" : 0.6046511627906976, - "matched_token_number" : 26 - }, "SortAlgo1_2-SortAlgo1_6" : { "minimal_similarity" : 0.6181818181818182, - "maximum_similarity" : 0.8095238095238095, + "maximum_similarity" : 0.7906976744186046, "matched_token_number" : 34 }, "SortAlgo-SortAlgo3_5" : { - "minimal_similarity" : 0.375, - "maximum_similarity" : 0.5121951219512195, - "matched_token_number" : 21 + "minimal_similarity" : 0.4107142857142857, + "maximum_similarity" : 0.5609756097560976, + "matched_token_number" : 23 }, "SortAlgo1_2-SortAlgo1_3" : { "minimal_similarity" : 0.6206896551724138, @@ -854,9 +854,9 @@ "matched_token_number" : 36 }, "SortAlgo1_2-SortAlgo1_4" : { - "minimal_similarity" : 0.6, - "maximum_similarity" : 0.7857142857142857, - "matched_token_number" : 33 + "minimal_similarity" : 0.7090909090909091, + "maximum_similarity" : 0.9069767441860465, + "matched_token_number" : 39 } } }, { @@ -865,12 +865,12 @@ }, "tests" : { "SortAlgo-SortAlgo5" : { - "minimal_similarity" : 0.2558139534883721, - "maximum_similarity" : 0.2682926829268293, - "matched_token_number" : 11 + "minimal_similarity" : 0.27906976744186046, + "maximum_similarity" : 0.2926829268292683, + "matched_token_number" : 12 }, "SortAlgo-SortAlgo6" : { - "minimal_similarity" : 0.4375, + "minimal_similarity" : 0.42857142857142855, "maximum_similarity" : 0.5121951219512195, "matched_token_number" : 21 }, @@ -880,13 +880,13 @@ "matched_token_number" : 38 }, "SortAlgo3_5-SortAlgo3_6" : { - "minimal_similarity" : 0.16071428571428573, - "maximum_similarity" : 0.16363636363636364, - "matched_token_number" : 9 + "minimal_similarity" : 0.17857142857142858, + "maximum_similarity" : 0.17857142857142858, + "matched_token_number" : 10 }, "SortAlgo6-SortAlgo7" : { "minimal_similarity" : 0.19642857142857142, - "maximum_similarity" : 0.22916666666666666, + "maximum_similarity" : 0.22448979591836735, "matched_token_number" : 11 }, "SortAlgo1_3-SortAlgo7" : { @@ -896,7 +896,7 @@ }, "SortAlgo1_3-SortAlgo6" : { "minimal_similarity" : 0.3103448275862069, - "maximum_similarity" : 0.375, + "maximum_similarity" : 0.3673469387755102, "matched_token_number" : 18 }, "SortAlgo-SortAlgo1" : { @@ -930,19 +930,19 @@ "matched_token_number" : 0 }, "SortAlgo-SortAlgo4" : { - "minimal_similarity" : 0.5714285714285714, + "minimal_similarity" : 0.5581395348837209, "maximum_similarity" : 0.5853658536585366, "matched_token_number" : 24 }, "SortAlgo1_3-SortAlgo4" : { "minimal_similarity" : 0.3793103448275862, - "maximum_similarity" : 0.5238095238095238, + "maximum_similarity" : 0.5116279069767442, "matched_token_number" : 22 }, "SortAlgo2-SortAlgo2_5" : { - "minimal_similarity" : 0.2558139534883721, - "maximum_similarity" : 0.2682926829268293, - "matched_token_number" : 11 + "minimal_similarity" : 0.27906976744186046, + "maximum_similarity" : 0.2926829268292683, + "matched_token_number" : 12 }, "SortAlgo1_2-SortAlgo2" : { "minimal_similarity" : 0.7454545454545455, @@ -961,22 +961,22 @@ }, "SortAlgo1_2-SortAlgo4" : { "minimal_similarity" : 0.4909090909090909, - "maximum_similarity" : 0.6428571428571429, + "maximum_similarity" : 0.627906976744186, "matched_token_number" : 27 }, "SortAlgo5-SortAlgo7" : { - "minimal_similarity" : 0.17857142857142858, - "maximum_similarity" : 0.23255813953488372, - "matched_token_number" : 10 - }, - "SortAlgo1_2-SortAlgo5" : { - "minimal_similarity" : 0.2, + "minimal_similarity" : 0.19642857142857142, "maximum_similarity" : 0.2558139534883721, "matched_token_number" : 11 }, + "SortAlgo1_2-SortAlgo5" : { + "minimal_similarity" : 0.21818181818181817, + "maximum_similarity" : 0.27906976744186046, + "matched_token_number" : 12 + }, "SortAlgo1_2-SortAlgo6" : { "minimal_similarity" : 0.38181818181818183, - "maximum_similarity" : 0.4375, + "maximum_similarity" : 0.42857142857142855, "matched_token_number" : 21 }, "SortAlgo1_2-SortAlgo7" : { @@ -985,28 +985,28 @@ "matched_token_number" : 38 }, "SortAlgo1-SortAlgo2_5" : { - "minimal_similarity" : 0.2558139534883721, - "maximum_similarity" : 0.2682926829268293, - "matched_token_number" : 11 + "minimal_similarity" : 0.27906976744186046, + "maximum_similarity" : 0.2926829268292683, + "matched_token_number" : 12 }, "SortAlgo1_3-SortAlgo3_6" : { "minimal_similarity" : 0.3103448275862069, - "maximum_similarity" : 0.32727272727272727, + "maximum_similarity" : 0.32142857142857145, "matched_token_number" : 18 }, "SortAlgo4-SortAlgo5" : { "minimal_similarity" : 0.2558139534883721, - "maximum_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.2558139534883721, "matched_token_number" : 11 }, "SortAlgo4-SortAlgo6" : { - "minimal_similarity" : 0.3125, - "maximum_similarity" : 0.35714285714285715, + "minimal_similarity" : 0.30612244897959184, + "maximum_similarity" : 0.3488372093023256, "matched_token_number" : 15 }, "SortAlgo4-SortAlgo7" : { "minimal_similarity" : 0.17857142857142858, - "maximum_similarity" : 0.23809523809523808, + "maximum_similarity" : 0.23255813953488372, "matched_token_number" : 10 }, "SortAlgo1_4-SortAlgo3_5" : { @@ -1015,8 +1015,8 @@ "matched_token_number" : 0 }, "SortAlgo1_4-SortAlgo3_6" : { - "minimal_similarity" : 0.34545454545454546, - "maximum_similarity" : 0.4523809523809524, + "minimal_similarity" : 0.3392857142857143, + "maximum_similarity" : 0.4418604651162791, "matched_token_number" : 19 }, "SortAlgo1_5-SortAlgo3_6" : { @@ -1040,9 +1040,9 @@ "matched_token_number" : 31 }, "SortAlgo1_6-SortAlgo3_6" : { - "minimal_similarity" : 0.5454545454545454, - "maximum_similarity" : 0.7142857142857143, - "matched_token_number" : 30 + "minimal_similarity" : 0.5535714285714286, + "maximum_similarity" : 0.7209302325581395, + "matched_token_number" : 31 }, "SortAlgo-SortAlgo4d2" : { "minimal_similarity" : 0.6326530612244898, @@ -1056,38 +1056,38 @@ }, "SortAlgo1_4-SortAlgo3" : { "minimal_similarity" : 0.35185185185185186, - "maximum_similarity" : 0.4523809523809524, + "maximum_similarity" : 0.4418604651162791, "matched_token_number" : 19 }, "SortAlgo3-SortAlgo3_5" : { - "minimal_similarity" : 0.16071428571428573, - "maximum_similarity" : 0.16666666666666666, - "matched_token_number" : 9 + "minimal_similarity" : 0.17857142857142858, + "maximum_similarity" : 0.18518518518518517, + "matched_token_number" : 10 }, "SortAlgo1_4-SortAlgo4" : { - "minimal_similarity" : 0.7619047619047619, - "maximum_similarity" : 0.7619047619047619, - "matched_token_number" : 32 + "minimal_similarity" : 0.7674418604651163, + "maximum_similarity" : 0.7674418604651163, + "matched_token_number" : 33 }, "SortAlgo3-SortAlgo3_6" : { - "minimal_similarity" : 0.5818181818181818, + "minimal_similarity" : 0.5714285714285714, "maximum_similarity" : 0.5925925925925926, "matched_token_number" : 32 }, "SortAlgo1_4-SortAlgo2" : { - "minimal_similarity" : 0.5476190476190477, + "minimal_similarity" : 0.5348837209302325, "maximum_similarity" : 0.5609756097560976, "matched_token_number" : 23 }, "SortAlgo1_4-SortAlgo7" : { "minimal_similarity" : 0.30357142857142855, - "maximum_similarity" : 0.40476190476190477, + "maximum_similarity" : 0.3953488372093023, "matched_token_number" : 17 }, "SortAlgo1_4-SortAlgo5" : { - "minimal_similarity" : 0.23255813953488372, - "maximum_similarity" : 0.23809523809523808, - "matched_token_number" : 10 + "minimal_similarity" : 0.2558139534883721, + "maximum_similarity" : 0.2558139534883721, + "matched_token_number" : 11 }, "SortAlgo2-SortAlgo3_5" : { "minimal_similarity" : 0.0, @@ -1095,17 +1095,17 @@ "matched_token_number" : 0 }, "SortAlgo1_4-SortAlgo6" : { - "minimal_similarity" : 0.4166666666666667, - "maximum_similarity" : 0.47619047619047616, + "minimal_similarity" : 0.40816326530612246, + "maximum_similarity" : 0.46511627906976744, "matched_token_number" : 20 }, "SortAlgo2-SortAlgo3_6" : { - "minimal_similarity" : 0.34545454545454546, + "minimal_similarity" : 0.3392857142857143, "maximum_similarity" : 0.4634146341463415, "matched_token_number" : 19 }, "SortAlgo1-SortAlgo3_6" : { - "minimal_similarity" : 0.34545454545454546, + "minimal_similarity" : 0.3392857142857143, "maximum_similarity" : 0.4634146341463415, "matched_token_number" : 19 }, @@ -1130,22 +1130,22 @@ "matched_token_number" : 0 }, "SortAlgo1_2-SortAlgo3_6" : { - "minimal_similarity" : 0.34545454545454546, + "minimal_similarity" : 0.3392857142857143, "maximum_similarity" : 0.34545454545454546, "matched_token_number" : 19 }, "SortAlgo-SortAlgo1_6" : { - "minimal_similarity" : 0.5952380952380952, + "minimal_similarity" : 0.5813953488372093, "maximum_similarity" : 0.6097560975609756, "matched_token_number" : 25 }, "SortAlgo-SortAlgo1_5" : { - "minimal_similarity" : 0.2558139534883721, - "maximum_similarity" : 0.2682926829268293, - "matched_token_number" : 11 + "minimal_similarity" : 0.27906976744186046, + "maximum_similarity" : 0.2926829268292683, + "matched_token_number" : 12 }, "SortAlgo-SortAlgo1_4" : { - "minimal_similarity" : 0.5476190476190477, + "minimal_similarity" : 0.5348837209302325, "maximum_similarity" : 0.5609756097560976, "matched_token_number" : 23 }, @@ -1156,7 +1156,7 @@ }, "SortAlgo1_6-SortAlgo4d1" : { "minimal_similarity" : 0.3541666666666667, - "maximum_similarity" : 0.40476190476190477, + "maximum_similarity" : 0.3953488372093023, "matched_token_number" : 17 }, "SortAlgo4d2-SortAlgo7" : { @@ -1166,7 +1166,7 @@ }, "SortAlgo1_6-SortAlgo4d2" : { "minimal_similarity" : 0.3469387755102041, - "maximum_similarity" : 0.40476190476190477, + "maximum_similarity" : 0.3953488372093023, "matched_token_number" : 17 }, "SortAlgo4d2-SortAlgo5" : { @@ -1176,12 +1176,12 @@ }, "SortAlgo4d2-SortAlgo6" : { "minimal_similarity" : 0.3469387755102041, - "maximum_similarity" : 0.3541666666666667, + "maximum_similarity" : 0.3469387755102041, "matched_token_number" : 17 }, "SortAlgo1_6-SortAlgo4d3" : { "minimal_similarity" : 0.3617021276595745, - "maximum_similarity" : 0.40476190476190477, + "maximum_similarity" : 0.3953488372093023, "matched_token_number" : 17 }, "SortAlgo1_5-SortAlgo2_5" : { @@ -1210,7 +1210,7 @@ "matched_token_number" : 31 }, "SortAlgo2-SortAlgo4" : { - "minimal_similarity" : 0.5714285714285714, + "minimal_similarity" : 0.5581395348837209, "maximum_similarity" : 0.5853658536585366, "matched_token_number" : 24 }, @@ -1220,13 +1220,13 @@ "matched_token_number" : 29 }, "SortAlgo1_6-SortAlgo2_5" : { - "minimal_similarity" : 0.2558139534883721, - "maximum_similarity" : 0.2619047619047619, - "matched_token_number" : 11 + "minimal_similarity" : 0.27906976744186046, + "maximum_similarity" : 0.27906976744186046, + "matched_token_number" : 12 }, "SortAlgo1_4-SortAlgo4d1" : { "minimal_similarity" : 0.3541666666666667, - "maximum_similarity" : 0.40476190476190477, + "maximum_similarity" : 0.3953488372093023, "matched_token_number" : 17 }, "SortAlgo1_5-SortAlgo4d3" : { @@ -1236,7 +1236,7 @@ }, "SortAlgo1_4-SortAlgo4d2" : { "minimal_similarity" : 0.3469387755102041, - "maximum_similarity" : 0.40476190476190477, + "maximum_similarity" : 0.3953488372093023, "matched_token_number" : 17 }, "SortAlgo1_5-SortAlgo4d2" : { @@ -1246,7 +1246,7 @@ }, "SortAlgo1_4-SortAlgo4d3" : { "minimal_similarity" : 0.3617021276595745, - "maximum_similarity" : 0.40476190476190477, + "maximum_similarity" : 0.3953488372093023, "matched_token_number" : 17 }, "SortAlgo1_5-SortAlgo4d1" : { @@ -1280,9 +1280,9 @@ "matched_token_number" : 29 }, "SortAlgo2-SortAlgo5" : { - "minimal_similarity" : 0.2558139534883721, - "maximum_similarity" : 0.2682926829268293, - "matched_token_number" : 11 + "minimal_similarity" : 0.27906976744186046, + "maximum_similarity" : 0.2926829268292683, + "matched_token_number" : 12 }, "SortAlgo4d1-SortAlgo4d3" : { "minimal_similarity" : 0.9375, @@ -1290,19 +1290,19 @@ "matched_token_number" : 45 }, "SortAlgo2-SortAlgo6" : { - "minimal_similarity" : 0.4375, + "minimal_similarity" : 0.42857142857142855, "maximum_similarity" : 0.5121951219512195, "matched_token_number" : 21 }, "SortAlgo1_6-SortAlgo7" : { "minimal_similarity" : 0.25, - "maximum_similarity" : 0.3333333333333333, + "maximum_similarity" : 0.32558139534883723, "matched_token_number" : 14 }, "SortAlgo3_6-SortAlgo6" : { - "minimal_similarity" : 0.7272727272727273, - "maximum_similarity" : 0.8333333333333334, - "matched_token_number" : 40 + "minimal_similarity" : 0.7321428571428571, + "maximum_similarity" : 0.8367346938775511, + "matched_token_number" : 41 }, "SortAlgo2_5-SortAlgo3_5" : { "minimal_similarity" : 0.5357142857142857, @@ -1321,11 +1321,11 @@ }, "SortAlgo3_6-SortAlgo7" : { "minimal_similarity" : 0.19642857142857142, - "maximum_similarity" : 0.2, + "maximum_similarity" : 0.19642857142857142, "matched_token_number" : 11 }, "SortAlgo4d3-SortAlgo6" : { - "minimal_similarity" : 0.3541666666666667, + "minimal_similarity" : 0.3469387755102041, "maximum_similarity" : 0.3617021276595745, "matched_token_number" : 17 }, @@ -1340,19 +1340,19 @@ "matched_token_number" : 0 }, "SortAlgo1_4-SortAlgo2_5" : { - "minimal_similarity" : 0.23255813953488372, - "maximum_similarity" : 0.23809523809523808, - "matched_token_number" : 10 + "minimal_similarity" : 0.2558139534883721, + "maximum_similarity" : 0.2558139534883721, + "matched_token_number" : 11 }, "SortAlgo1-SortAlgo4" : { - "minimal_similarity" : 0.5714285714285714, + "minimal_similarity" : 0.5581395348837209, "maximum_similarity" : 0.5853658536585366, "matched_token_number" : 24 }, "SortAlgo1-SortAlgo5" : { - "minimal_similarity" : 0.2558139534883721, - "maximum_similarity" : 0.2682926829268293, - "matched_token_number" : 11 + "minimal_similarity" : 0.27906976744186046, + "maximum_similarity" : 0.2926829268292683, + "matched_token_number" : 12 }, "SortAlgo1-SortAlgo2" : { "minimal_similarity" : 1.0, @@ -1360,8 +1360,8 @@ "matched_token_number" : 41 }, "SortAlgo3_6-SortAlgo4" : { - "minimal_similarity" : 0.2545454545454545, - "maximum_similarity" : 0.3333333333333333, + "minimal_similarity" : 0.25, + "maximum_similarity" : 0.32558139534883723, "matched_token_number" : 14 }, "SortAlgo1-SortAlgo3" : { @@ -1375,12 +1375,12 @@ "matched_token_number" : 0 }, "SortAlgo1_6-SortAlgo2" : { - "minimal_similarity" : 0.5952380952380952, + "minimal_similarity" : 0.5813953488372093, "maximum_similarity" : 0.6097560975609756, "matched_token_number" : 25 }, "SortAlgo1-SortAlgo6" : { - "minimal_similarity" : 0.4375, + "minimal_similarity" : 0.42857142857142855, "maximum_similarity" : 0.5121951219512195, "matched_token_number" : 21 }, @@ -1390,33 +1390,33 @@ "matched_token_number" : 38 }, "SortAlgo1_2-SortAlgo2_5" : { - "minimal_similarity" : 0.2, - "maximum_similarity" : 0.2558139534883721, - "matched_token_number" : 11 + "minimal_similarity" : 0.21818181818181817, + "maximum_similarity" : 0.27906976744186046, + "matched_token_number" : 12 }, "SortAlgo1_6-SortAlgo6" : { - "minimal_similarity" : 0.7916666666666666, - "maximum_similarity" : 0.9047619047619048, - "matched_token_number" : 38 + "minimal_similarity" : 0.7959183673469388, + "maximum_similarity" : 0.9069767441860465, + "matched_token_number" : 39 }, "SortAlgo-SortAlgo2_5" : { - "minimal_similarity" : 0.2558139534883721, - "maximum_similarity" : 0.2682926829268293, - "matched_token_number" : 11 + "minimal_similarity" : 0.27906976744186046, + "maximum_similarity" : 0.2926829268292683, + "matched_token_number" : 12 }, "SortAlgo1_6-SortAlgo5" : { - "minimal_similarity" : 0.2558139534883721, - "maximum_similarity" : 0.2619047619047619, - "matched_token_number" : 11 + "minimal_similarity" : 0.27906976744186046, + "maximum_similarity" : 0.27906976744186046, + "matched_token_number" : 12 }, "SortAlgo1_6-SortAlgo4" : { - "minimal_similarity" : 0.5714285714285714, - "maximum_similarity" : 0.5714285714285714, + "minimal_similarity" : 0.5581395348837209, + "maximum_similarity" : 0.5581395348837209, "matched_token_number" : 24 }, "SortAlgo1_6-SortAlgo3" : { "minimal_similarity" : 0.35185185185185186, - "maximum_similarity" : 0.4523809523809524, + "maximum_similarity" : 0.4418604651162791, "matched_token_number" : 19 }, "SortAlgo1_5-SortAlgo6" : { @@ -1425,14 +1425,14 @@ "matched_token_number" : 0 }, "SortAlgo2_5-SortAlgo7" : { - "minimal_similarity" : 0.17857142857142858, - "maximum_similarity" : 0.23255813953488372, - "matched_token_number" : 10 + "minimal_similarity" : 0.19642857142857142, + "maximum_similarity" : 0.2558139534883721, + "matched_token_number" : 11 }, "SortAlgo1_5-SortAlgo7" : { - "minimal_similarity" : 0.17857142857142858, - "maximum_similarity" : 0.23255813953488372, - "matched_token_number" : 10 + "minimal_similarity" : 0.19642857142857142, + "maximum_similarity" : 0.2558139534883721, + "matched_token_number" : 11 }, "SortAlgo1-SortAlgo4d3" : { "minimal_similarity" : 0.6595744680851063, @@ -1441,7 +1441,7 @@ }, "SortAlgo1_5-SortAlgo4" : { "minimal_similarity" : 0.2558139534883721, - "maximum_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.2558139534883721, "matched_token_number" : 11 }, "SortAlgo1_5-SortAlgo5" : { @@ -1460,14 +1460,14 @@ "matched_token_number" : 31 }, "SortAlgo1_5-SortAlgo2" : { - "minimal_similarity" : 0.2558139534883721, - "maximum_similarity" : 0.2682926829268293, - "matched_token_number" : 11 + "minimal_similarity" : 0.27906976744186046, + "maximum_similarity" : 0.2926829268292683, + "matched_token_number" : 12 }, "SortAlgo3_5-SortAlgo6" : { - "minimal_similarity" : 0.16071428571428573, - "maximum_similarity" : 0.1875, - "matched_token_number" : 9 + "minimal_similarity" : 0.17857142857142858, + "maximum_similarity" : 0.20408163265306123, + "matched_token_number" : 10 }, "SortAlgo3_5-SortAlgo7" : { "minimal_similarity" : 0.0, @@ -1510,12 +1510,12 @@ "matched_token_number" : 31 }, "SortAlgo1_5-SortAlgo1_6" : { - "minimal_similarity" : 0.2558139534883721, - "maximum_similarity" : 0.2619047619047619, - "matched_token_number" : 11 + "minimal_similarity" : 0.27906976744186046, + "maximum_similarity" : 0.27906976744186046, + "matched_token_number" : 12 }, "SortAlgo3_6-SortAlgo4d2" : { - "minimal_similarity" : 0.3090909090909091, + "minimal_similarity" : 0.30357142857142855, "maximum_similarity" : 0.3469387755102041, "matched_token_number" : 17 }, @@ -1525,33 +1525,33 @@ "matched_token_number" : 10 }, "SortAlgo4d1-SortAlgo6" : { - "minimal_similarity" : 0.3541666666666667, + "minimal_similarity" : 0.3469387755102041, "maximum_similarity" : 0.3541666666666667, "matched_token_number" : 17 }, "SortAlgo3_6-SortAlgo4d1" : { - "minimal_similarity" : 0.3090909090909091, + "minimal_similarity" : 0.30357142857142855, "maximum_similarity" : 0.3541666666666667, "matched_token_number" : 17 }, "SortAlgo4-SortAlgo4d1" : { "minimal_similarity" : 0.2708333333333333, - "maximum_similarity" : 0.30952380952380953, + "maximum_similarity" : 0.3023255813953488, "matched_token_number" : 13 }, "SortAlgo3_6-SortAlgo4d3" : { - "minimal_similarity" : 0.3090909090909091, + "minimal_similarity" : 0.30357142857142855, "maximum_similarity" : 0.3617021276595745, "matched_token_number" : 17 }, "SortAlgo4-SortAlgo4d2" : { "minimal_similarity" : 0.2653061224489796, - "maximum_similarity" : 0.30952380952380953, + "maximum_similarity" : 0.3023255813953488, "matched_token_number" : 13 }, "SortAlgo4-SortAlgo4d3" : { "minimal_similarity" : 0.2765957446808511, - "maximum_similarity" : 0.30952380952380953, + "maximum_similarity" : 0.3023255813953488, "matched_token_number" : 13 }, "SortAlgo3_5-SortAlgo4" : { @@ -1581,15 +1581,15 @@ }, "SortAlgo2_5-SortAlgo4" : { "minimal_similarity" : 0.2558139534883721, - "maximum_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.2558139534883721, "matched_token_number" : 11 }, - "SortAlgo2_5-SortAlgo3" : { + "SortAlgo3_5-SortAlgo4d1" : { "minimal_similarity" : 0.0, "maximum_similarity" : 0.0, "matched_token_number" : 0 }, - "SortAlgo3_5-SortAlgo4d1" : { + "SortAlgo2_5-SortAlgo3" : { "minimal_similarity" : 0.0, "maximum_similarity" : 0.0, "matched_token_number" : 0 @@ -1615,17 +1615,17 @@ "matched_token_number" : 41 }, "SortAlgo1-SortAlgo1_6" : { - "minimal_similarity" : 0.5952380952380952, + "minimal_similarity" : 0.5813953488372093, "maximum_similarity" : 0.6097560975609756, "matched_token_number" : 25 }, "SortAlgo1-SortAlgo1_5" : { - "minimal_similarity" : 0.2558139534883721, - "maximum_similarity" : 0.2682926829268293, - "matched_token_number" : 11 + "minimal_similarity" : 0.27906976744186046, + "maximum_similarity" : 0.2926829268292683, + "matched_token_number" : 12 }, "SortAlgo1-SortAlgo1_4" : { - "minimal_similarity" : 0.5476190476190477, + "minimal_similarity" : 0.5348837209302325, "maximum_similarity" : 0.5609756097560976, "matched_token_number" : 23 }, @@ -1641,7 +1641,7 @@ }, "SortAlgo3-SortAlgo6" : { "minimal_similarity" : 0.5370370370370371, - "maximum_similarity" : 0.6041666666666666, + "maximum_similarity" : 0.5918367346938775, "matched_token_number" : 29 }, "SortAlgo2_5-SortAlgo4d2" : { @@ -1650,9 +1650,9 @@ "matched_token_number" : 0 }, "SortAlgo1_4-SortAlgo1_5" : { - "minimal_similarity" : 0.23255813953488372, - "maximum_similarity" : 0.23809523809523808, - "matched_token_number" : 10 + "minimal_similarity" : 0.2558139534883721, + "maximum_similarity" : 0.2558139534883721, + "matched_token_number" : 11 }, "SortAlgo3-SortAlgo5" : { "minimal_similarity" : 0.0, @@ -1660,13 +1660,13 @@ "matched_token_number" : 0 }, "SortAlgo1_4-SortAlgo1_6" : { - "minimal_similarity" : 0.5476190476190477, - "maximum_similarity" : 0.5476190476190477, + "minimal_similarity" : 0.5348837209302325, + "maximum_similarity" : 0.5348837209302325, "matched_token_number" : 23 }, "SortAlgo3-SortAlgo4" : { "minimal_similarity" : 0.25925925925925924, - "maximum_similarity" : 0.3333333333333333, + "maximum_similarity" : 0.32558139534883723, "matched_token_number" : 14 }, "SortAlgo1_3-SortAlgo1_5" : { @@ -1676,7 +1676,7 @@ }, "SortAlgo1_3-SortAlgo1_4" : { "minimal_similarity" : 0.46551724137931033, - "maximum_similarity" : 0.6428571428571429, + "maximum_similarity" : 0.627906976744186, "matched_token_number" : 27 }, "SortAlgo2_5-SortAlgo4d3" : { @@ -1686,22 +1686,22 @@ }, "SortAlgo1_3-SortAlgo1_6" : { "minimal_similarity" : 0.3103448275862069, - "maximum_similarity" : 0.42857142857142855, + "maximum_similarity" : 0.4186046511627907, "matched_token_number" : 18 }, "SortAlgo-SortAlgo3_6" : { - "minimal_similarity" : 0.34545454545454546, + "minimal_similarity" : 0.3392857142857143, "maximum_similarity" : 0.4634146341463415, "matched_token_number" : 19 }, "SortAlgo1_2-SortAlgo1_5" : { - "minimal_similarity" : 0.2, - "maximum_similarity" : 0.2558139534883721, - "matched_token_number" : 11 + "minimal_similarity" : 0.21818181818181817, + "maximum_similarity" : 0.27906976744186046, + "matched_token_number" : 12 }, "SortAlgo1_2-SortAlgo1_6" : { "minimal_similarity" : 0.45454545454545453, - "maximum_similarity" : 0.5952380952380952, + "maximum_similarity" : 0.5813953488372093, "matched_token_number" : 25 }, "SortAlgo-SortAlgo3_5" : { @@ -1716,7 +1716,7 @@ }, "SortAlgo1_2-SortAlgo1_4" : { "minimal_similarity" : 0.41818181818181815, - "maximum_similarity" : 0.5476190476190477, + "maximum_similarity" : 0.5348837209302325, "matched_token_number" : 23 } } diff --git a/language-antlr-utils/.gitignore b/language-antlr-utils/.gitignore new file mode 100644 index 000000000..5ff6309b7 --- /dev/null +++ b/language-antlr-utils/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/language-antlr-utils/pom.xml b/language-antlr-utils/pom.xml new file mode 100644 index 000000000..c5542fbfc --- /dev/null +++ b/language-antlr-utils/pom.xml @@ -0,0 +1,71 @@ + + + 4.0.0 + + de.jplag + aggregator + ${revision} + + language-antlr-utils + language-antlr-utils + Contains default implementations for anltr base language modules + + + + org.antlr + antlr4-runtime + 4.13.1 + + + de.jplag + language-api + ${revision} + + + de.jplag + language-testutils + ${revision} + test-jar + test + + + + + + + org.antlr + antlr4-maven-plugin + + ${basedir}/src/test/antlr4 + ${basedir}/target/generated-test-sources/antlr4 + + + + + antlr4 + + generate-test-sources + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add-test-sources + + add-test-source + + generate-test-sources + + + ${basedir}/target/generated-test-sources/antlr4 + + + + + + + + diff --git a/language-antlr-utils/src/main/java/de/jplag/antlr/AbstractAntlrLanguage.java b/language-antlr-utils/src/main/java/de/jplag/antlr/AbstractAntlrLanguage.java new file mode 100644 index 000000000..93f6ace30 --- /dev/null +++ b/language-antlr-utils/src/main/java/de/jplag/antlr/AbstractAntlrLanguage.java @@ -0,0 +1,53 @@ +package de.jplag.antlr; + +import java.io.File; +import java.util.List; +import java.util.Set; + +import de.jplag.Language; +import de.jplag.ParsingException; +import de.jplag.Token; + +/** + * Base class for Antlr languages. Handle the parse function from {@link Language} + *

+ * You can either pass the parser to the super constructor, or implement the initializeParser method. That allows you to + * access class members, like language specific options. + */ +public abstract class AbstractAntlrLanguage implements Language { + private AbstractAntlrParserAdapter parser; + + /** + * New instance + * @param parser The parser for source files + */ + protected AbstractAntlrLanguage(AbstractAntlrParserAdapter parser) { + this.parser = parser; + } + + /** + * New instance, without pre initialized parser. If you use this constructor, you need to override the initializeParser + * method. + */ + protected AbstractAntlrLanguage() { + this.parser = null; + } + + @Override + public List parse(Set files) throws ParsingException { + if (this.parser == null) { + this.parser = this.initializeParser(); + } + + return this.parser.parse(files); + } + + /** + * Lazily creates the parser. Has to be implemented, if no parser is passed in the constructor. + * @return The newly initialized parser + */ + protected AbstractAntlrParserAdapter initializeParser() { + throw new UnsupportedOperationException( + String.format("The initializeParser method needs to be implemented for %s", this.getClass().getName())); + } +} diff --git a/language-antlr-utils/src/main/java/de/jplag/antlr/AbstractAntlrListener.java b/language-antlr-utils/src/main/java/de/jplag/antlr/AbstractAntlrListener.java new file mode 100644 index 000000000..f4144b72e --- /dev/null +++ b/language-antlr-utils/src/main/java/de/jplag/antlr/AbstractAntlrListener.java @@ -0,0 +1,163 @@ +package de.jplag.antlr; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.function.Predicate; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +/** + * Base class for Antlr listeners. This is a quasi-static class that is only created once per language. Use by calling + * the visit methods in the overwritten constructor. + */ +public abstract class AbstractAntlrListener { + private final List> contextVisitors; + private final List terminalVisitors; + + /** + * New instance + */ + protected AbstractAntlrListener() { + contextVisitors = new ArrayList<>(); + terminalVisitors = new ArrayList<>(); + } + + /** + * Visit the given node. + * @param antlrType The antlr type of the node. + * @param condition An additional condition for the visit. + * @return A visitor for the node. + * @param The class of the node. + */ + @SuppressWarnings("unchecked") + public ContextVisitor visit(Class antlrType, Predicate condition) { + Predicate typeCheck = rule -> rule.getClass() == antlrType; + ContextVisitor visitor = new ContextVisitor<>(typeCheck.and(condition)); + contextVisitors.add((ContextVisitor) visitor); + return visitor; + } + + /** + * Visit the given node. + * @param antlrType The antlr type of the node. + * @return A visitor for the node. + * @param The class of the node. + */ + public ContextVisitor visit(Class antlrType) { + return visit(antlrType, ignore -> true); + } + + /** + * Visit the given terminal. + * @param terminalType The type of the terminal. + * @param condition An additional condition for the visit. + * @return A visitor for the node. + */ + public TerminalVisitor visit(int terminalType, Predicate condition) { + Predicate typeCheck = rule -> rule.getType() == terminalType; + TerminalVisitor visitor = new TerminalVisitor(typeCheck.and(condition)); + terminalVisitors.add(visitor); + return visitor; + } + + /** + * Visit the given terminal. + * @param terminalType The type of the terminal. + * @return A visitor for the node. + */ + public TerminalVisitor visit(int terminalType) { + return visit(terminalType, ignore -> true); + } + + /** + * Called by {@link InternalListener#visitTerminal(TerminalNode)} as part of antlr framework. + */ + void visitTerminal(HandlerData data) { + this.terminalVisitors.stream().filter(visitor -> visitor.matches(data.entity())).forEach(visitor -> visitor.enter(data)); + } + + /** + * Called by {@link InternalListener#enterEveryRule(ParserRuleContext)} as part of antlr framework. + */ + void enterEveryRule(HandlerData data) { + this.contextVisitors.stream().filter(visitor -> visitor.matches(data.entity())).forEach(visitor -> visitor.enter(data)); + } + + /** + * Called by {@link InternalListener#exitEveryRule(ParserRuleContext)} as part of antlr framework. + */ + void exitEveryRule(HandlerData data) { + this.contextVisitors.stream().filter(visitor -> visitor.matches(data.entity())).forEach(visitor -> visitor.exit(data)); + } + + /** + * Searches the ancestors of an element for an element of the specific type. + * @param context the current element to start the search from. + * @param ancestor the class representing the type to search for. + * @param stops the types of elements to stop the upward search at. + * @param the type of the element to search for. + * @return an ancestor of the specified type, or null if not found. + */ + @SafeVarargs + protected static T getAncestor(ParserRuleContext context, Class ancestor, + Class... stops) { + ParserRuleContext currentContext = context; + Set> forbidden = Set.of(stops); + boolean abort = false; + while (currentContext != null && !abort) { + if (currentContext.getClass() == ancestor) { + return ancestor.cast(currentContext); + } + if (forbidden.contains(currentContext.getClass())) { + abort = true; + } + + currentContext = currentContext.getParent(); + } + + return null; + } + + /** + * {@return true if an ancestor of the specified type exists} + * @param context the current element to start the search from. + * @param parent the class representing the type to search for. + * @param stops the types of elements to stop the upward search at. + * @see #getAncestor(ParserRuleContext, Class, Class[]) + */ + @SafeVarargs + protected static boolean hasAncestor(ParserRuleContext context, Class parent, + Class... stops) { + return getAncestor(context, parent, stops) != null; + } + + /** + * Searches a subtree for a descendant of a specific type. Search is done breath-first. + * @param context the context to search the subtree from. + * @param descendant the class representing the type to search for. + * @param the type to search for. + * @return the first appearance of an element of the given type in the subtree, or null if no such element exists. + */ + protected static T getDescendant(ParserRuleContext context, Class descendant) { + // simple iterative bfs + ArrayDeque queue = new ArrayDeque<>(); + queue.add(context); + while (!queue.isEmpty()) { + ParserRuleContext next = queue.removeFirst(); + for (ParseTree tree : next.children) { + if (tree.getClass() == descendant) { + return descendant.cast(tree); + } + if (tree instanceof ParserRuleContext parserRuleContext) { + queue.addLast(parserRuleContext); + } + } + } + return null; + } +} diff --git a/language-antlr-utils/src/main/java/de/jplag/antlr/AbstractAntlrParserAdapter.java b/language-antlr-utils/src/main/java/de/jplag/antlr/AbstractAntlrParserAdapter.java new file mode 100644 index 000000000..1644ccf7b --- /dev/null +++ b/language-antlr-utils/src/main/java/de/jplag/antlr/AbstractAntlrParserAdapter.java @@ -0,0 +1,103 @@ +package de.jplag.antlr; + +import java.io.File; +import java.io.IOException; +import java.io.Reader; +import java.util.List; +import java.util.Set; + +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.Parser; +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.ParseTreeWalker; + +import de.jplag.AbstractParser; +import de.jplag.ParsingException; +import de.jplag.Token; +import de.jplag.util.FileUtils; + +/** + * Base class for Antlr parser adapters + * @param The type of the antlr parser + */ +public abstract class AbstractAntlrParserAdapter extends AbstractParser { + + private final boolean extractsSemantics; + + /** + * New instance + * @param extractsSemantics If true, the listener will extract semantics along with every token + */ + protected AbstractAntlrParserAdapter(boolean extractsSemantics) { + this.extractsSemantics = extractsSemantics; + } + + /** + * New instance + */ + protected AbstractAntlrParserAdapter() { + this(false); + } + + /** + * Parsers the set of files + * @param files The files + * @return The extracted tokens + * @throws ParsingException If anything goes wrong + */ + public List parse(Set files) throws ParsingException { + TokenCollector collector = new TokenCollector(extractsSemantics); + for (File file : files) { + parseFile(file, collector); + } + return collector.getTokens(); + } + + private void parseFile(File file, TokenCollector collector) throws ParsingException { + collector.enterFile(file); + try (Reader reader = FileUtils.openFileReader(file)) { + Lexer lexer = this.createLexer(CharStreams.fromReader(reader)); + CommonTokenStream tokenStream = new CommonTokenStream(lexer); + T parser = this.createParser(tokenStream); + ParserRuleContext entryContext = this.getEntryContext(parser); + ParseTreeWalker treeWalker = new ParseTreeWalker(); + InternalListener listener = new InternalListener(this.getListener(), collector); + for (ParseTree child : entryContext.children) { + treeWalker.walk(listener, child); + } + } catch (IOException exception) { + throw new ParsingException(file, exception.getMessage(), exception); + } + collector.addFileEndToken(); + } + + /** + * Creates the antlr lexer + * @param input The input stream + * @return The lexer + */ + protected abstract Lexer createLexer(CharStream input); + + /** + * Creates the antlr parser + * @param tokenStream The token input + * @return The parser + */ + protected abstract T createParser(CommonTokenStream tokenStream); + + /** + * Extracts the core context from the parser. Should return the root context for the entire source file + * @param parser The parser + * @return The root context + */ + protected abstract ParserRuleContext getEntryContext(T parser); + + /** + * @return The listener. Should be created once statically since it never changes. + */ + protected abstract AbstractAntlrListener getListener(); +} diff --git a/language-antlr-utils/src/main/java/de/jplag/antlr/AbstractVisitor.java b/language-antlr-utils/src/main/java/de/jplag/antlr/AbstractVisitor.java new file mode 100644 index 000000000..cad061e19 --- /dev/null +++ b/language-antlr-utils/src/main/java/de/jplag/antlr/AbstractVisitor.java @@ -0,0 +1,122 @@ +package de.jplag.antlr; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.*; + +import org.antlr.v4.runtime.Token; + +import de.jplag.TokenType; +import de.jplag.semantics.CodeSemantics; +import de.jplag.semantics.VariableRegistry; + +/** + * The abstract visitor. + * @param The type of the visited entity. + */ +public abstract class AbstractVisitor { + private final Predicate condition; + private final List>> entryHandlers; + private TokenType entryTokenType; + private Function entrySemantics; + + /** + * @param condition The condition for the visit. + */ + AbstractVisitor(Predicate condition) { + this.condition = condition; + this.entryHandlers = new ArrayList<>(); + } + + /** + * Add an action the visitor runs upon entering the entity. + * @param handler The action, takes the entity and the variable registry as parameter. + * @return Self + */ + public AbstractVisitor onEnter(BiConsumer handler) { + entryHandlers.add(handlerData -> handler.accept(handlerData.entity(), handlerData.variableRegistry())); + return this; + } + + /** + * Add an action the visitor runs upon entering the entity. + * @param handler The action, takes the entity as parameter. + * @return Self + */ + public AbstractVisitor onEnter(Consumer handler) { + entryHandlers.add(handlerData -> handler.accept(handlerData.entity())); + return this; + } + + /** + * Tell the visitor that it should generate a token upon entering the entity. Should only be invoked once per visitor. + * @param tokenType The type of the token. + * @return Self + */ + public AbstractVisitor mapEnter(TokenType tokenType) { + entryTokenType = tokenType; + return this; + } + + /** + * Tell the visitor that it should generate a token upon entering the entity. Should only be invoked once per visitor. + * Alias for {@link #mapEnter(TokenType)}. + * @param tokenType The type of the token. + * @return Self + */ + public AbstractVisitor map(TokenType tokenType) { + mapEnter(tokenType); + return this; + } + + /** + * Tell the visitor that if it generates a token upon entering the entity, it should have semantics. + * @param semanticsSupplier A function that takes the entity and returns the semantics. + * @return Self + */ + public AbstractVisitor withSemantics(Function semanticsSupplier) { + this.entrySemantics = semanticsSupplier; + return this; + } + + /** + * Tell the visitor that if it generates a token upon entering the entity, it should have semantics. + * @param semanticsSupplier A function that returns the semantics. + * @return Self + */ + public AbstractVisitor withSemantics(Supplier semanticsSupplier) { + this.entrySemantics = ignore -> semanticsSupplier.get(); + return this; + } + + /** + * Tell the visitor that if it generates a token upon entering the entity, it should have semantics of type control. + * @return Self + */ + public AbstractVisitor withControlSemantics() { + withSemantics(CodeSemantics::createControl); + return this; + } + + /** + * @param entity The entity to check. + * @return Whether to visit the entity. + */ + boolean matches(T entity) { + return this.condition.test(entity); + } + + /** + * Enter a given entity, injecting the needed dependencies. + */ + void enter(HandlerData data) { + addToken(data, entryTokenType, entrySemantics, this::extractEnterToken); + entryHandlers.forEach(handler -> handler.accept(data)); + } + + void addToken(HandlerData data, TokenType tokenType, Function semantics, Function extractToken) { + data.collector().addToken(tokenType, semantics, data.entity(), extractToken, data.variableRegistry()); + } + + abstract Token extractEnterToken(T entity); +} diff --git a/language-antlr-utils/src/main/java/de/jplag/antlr/ContextVisitor.java b/language-antlr-utils/src/main/java/de/jplag/antlr/ContextVisitor.java new file mode 100644 index 000000000..92dd4ae79 --- /dev/null +++ b/language-antlr-utils/src/main/java/de/jplag/antlr/ContextVisitor.java @@ -0,0 +1,139 @@ +package de.jplag.antlr; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.*; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.Token; + +import de.jplag.TokenType; +import de.jplag.semantics.CodeSemantics; +import de.jplag.semantics.VariableRegistry; + +/** + * The visitor for nodes, or contexts. + * @param The antlr type of the node. + */ +public class ContextVisitor extends AbstractVisitor { + private final List>> exitHandlers; + private TokenType exitToken; + private Function exitSemantics; + + ContextVisitor(Predicate condition) { + super(condition); + this.exitHandlers = new ArrayList<>(); + } + + /** + * Add an action the visitor runs upon exiting the entity. + * @param handler The action, takes the entity and the variable registry as parameter. + * @return Self + */ + public AbstractVisitor onExit(BiConsumer handler) { + exitHandlers.add(handlerData -> handler.accept(handlerData.entity(), handlerData.variableRegistry())); + return this; + } + + /** + * Add an action the visitor runs upon exiting the entity. + * @param handler The action, takes the entity as parameter. + * @return Self + */ + public AbstractVisitor onExit(Consumer handler) { + exitHandlers.add(handlerData -> handler.accept(handlerData.entity())); + return this; + } + + /** + * Tell the visitor that it should generate a token upon exiting the entity. Should only be invoked once per visitor. + * @param tokenType The type of the token. + * @return Self + */ + public ContextVisitor mapExit(TokenType tokenType) { + exitToken = tokenType; + return this; + } + + /** + * Tell the visitor that it should generate a token upon entering and one upon exiting the entity. Should only be + * invoked once per visitor. + * @param enterTokenType The type of the token generated on enter. + * @param exitTokenType The type of the token generated on exit. + * @return Self + */ + public ContextVisitor mapEnterExit(TokenType enterTokenType, TokenType exitTokenType) { + mapEnter(enterTokenType); + mapExit(exitTokenType); + return this; + } + + /** + * Tell the visitor that it should generate a token upon entering and one upon exiting the entity. Should only be + * invoked once per visitor. Alias for {@link #mapEnterExit(TokenType, TokenType)}. + * @param enterTokenType The type of the token generated on enter. + * @param exitTokenType The type of the token generated on exit. + * @return Self + */ + public ContextVisitor map(TokenType enterTokenType, TokenType exitTokenType) { + mapEnterExit(enterTokenType, exitTokenType); + return this; + } + + @Override + public ContextVisitor withSemantics(Function semantics) { + super.withSemantics(semantics); + this.exitSemantics = semantics; + return this; + } + + @Override + public ContextVisitor withSemantics(Supplier semantics) { + super.withSemantics(semantics); + this.exitSemantics = ignore -> semantics.get(); + return this; + } + + /** + * Tell the visitor that if it generates a token upon entering the entity, it should have semantics of type loop begin, + * same for the exit and loop end. + * @return Self + */ + public ContextVisitor withLoopSemantics() { + super.withSemantics(CodeSemantics::createLoopBegin); + this.exitSemantics = ignore -> CodeSemantics.createLoopEnd(); + return this; + } + + /** + * Tell the visitor that the entity represents a local scope. + * @return Self + */ + public ContextVisitor addLocalScope() { + onEnter((ignore, variableRegistry) -> variableRegistry.enterLocalScope()); + onExit((ignore, variableRegistry) -> variableRegistry.exitLocalScope()); + return this; + } + + /** + * Tell the visitor that the entity represents a class scope. + * @return Self + */ + public ContextVisitor addClassScope() { + onEnter((ignore, variableRegistry) -> variableRegistry.enterClass()); + onExit((ignore, variableRegistry) -> variableRegistry.exitClass()); + return this; + } + + /** + * Exit a given entity, injecting the needed dependencies. + */ + void exit(HandlerData data) { + addToken(data, exitToken, exitSemantics, ParserRuleContext::getStop); + exitHandlers.forEach(handler -> handler.accept(data)); + } + + Token extractEnterToken(T entity) { + return entity.getStart(); + } +} diff --git a/language-antlr-utils/src/main/java/de/jplag/antlr/HandlerData.java b/language-antlr-utils/src/main/java/de/jplag/antlr/HandlerData.java new file mode 100644 index 000000000..6c1bb4095 --- /dev/null +++ b/language-antlr-utils/src/main/java/de/jplag/antlr/HandlerData.java @@ -0,0 +1,9 @@ +package de.jplag.antlr; + +import de.jplag.semantics.VariableRegistry; + +/** + * Holds the data passed to the (quasi-static) listeners. + */ +record HandlerData(T entity, VariableRegistry variableRegistry, TokenCollector collector) { +} diff --git a/language-antlr-utils/src/main/java/de/jplag/antlr/InternalListener.java b/language-antlr-utils/src/main/java/de/jplag/antlr/InternalListener.java new file mode 100644 index 000000000..39178e0fb --- /dev/null +++ b/language-antlr-utils/src/main/java/de/jplag/antlr/InternalListener.java @@ -0,0 +1,48 @@ +package de.jplag.antlr; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTreeListener; +import org.antlr.v4.runtime.tree.TerminalNode; + +import de.jplag.semantics.VariableRegistry; + +/** + * Internal listener that implements pre-existing antlr methods that are called automatically. This listener is created + * for every file. + */ +class InternalListener implements ParseTreeListener { + private final AbstractAntlrListener listener; + private final TokenCollector collector; + protected final VariableRegistry variableRegistry; + + InternalListener(AbstractAntlrListener listener, TokenCollector collector) { + this.listener = listener; + this.collector = collector; + this.variableRegistry = new VariableRegistry(); + } + + @Override + public void visitTerminal(TerminalNode terminalNode) { + listener.visitTerminal(getHandlerData(terminalNode.getSymbol())); + } + + @Override + public void enterEveryRule(ParserRuleContext rule) { + listener.enterEveryRule(getHandlerData(rule)); + } + + @Override + public void exitEveryRule(ParserRuleContext rule) { + listener.exitEveryRule(getHandlerData(rule)); + } + + @Override + public void visitErrorNode(ErrorNode errorNode) { + // does nothing, because we do not handle error nodes right now. + } + + private HandlerData getHandlerData(T entity) { + return new HandlerData<>(entity, variableRegistry, collector); + } +} diff --git a/language-antlr-utils/src/main/java/de/jplag/antlr/TerminalVisitor.java b/language-antlr-utils/src/main/java/de/jplag/antlr/TerminalVisitor.java new file mode 100644 index 000000000..170f5d627 --- /dev/null +++ b/language-antlr-utils/src/main/java/de/jplag/antlr/TerminalVisitor.java @@ -0,0 +1,19 @@ +package de.jplag.antlr; + +import java.util.function.Predicate; + +import org.antlr.v4.runtime.Token; + +/** + * The visitor for terminals. + */ +public class TerminalVisitor extends AbstractVisitor { + + TerminalVisitor(Predicate condition) { + super(condition); + } + + Token extractEnterToken(Token token) { + return token; + } +} diff --git a/language-antlr-utils/src/main/java/de/jplag/antlr/TokenCollector.java b/language-antlr-utils/src/main/java/de/jplag/antlr/TokenCollector.java new file mode 100644 index 000000000..7a284d015 --- /dev/null +++ b/language-antlr-utils/src/main/java/de/jplag/antlr/TokenCollector.java @@ -0,0 +1,80 @@ +package de.jplag.antlr; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.Function; +import java.util.logging.Logger; + +import de.jplag.Token; +import de.jplag.TokenType; +import de.jplag.semantics.CodeSemantics; +import de.jplag.semantics.VariableRegistry; + +/** + * Collects the tokens during parsing. + */ +public class TokenCollector { + private static final Logger logger = Logger.getLogger(TokenCollector.class.getName()); + private final List collected; + private final boolean extractsSemantics; + private File file; + + /** + * @param extractsSemantics If semantics are extracted + */ + TokenCollector(boolean extractsSemantics) { + this.collected = new ArrayList<>(); + this.extractsSemantics = extractsSemantics; + } + + /** + * @return All collected tokens + */ + List getTokens() { + return Collections.unmodifiableList(this.collected); + } + + void addToken(TokenType jplagType, Function semanticsSupplier, T entity, + Function extractToken, VariableRegistry variableRegistry) { + if (jplagType == null) { + if (semanticsSupplier != null) { + logger.warning("Received semantics, but no token type, so no token was generated and the semantics discarded"); + } + return; + } + org.antlr.v4.runtime.Token antlrToken = extractToken.apply(entity); + int line = antlrToken.getLine(); + int column = antlrToken.getCharPositionInLine() + 1; + int length = antlrToken.getText().length(); + Token token; + if (extractsSemantics) { + if (semanticsSupplier == null) { + throw new IllegalStateException(String.format("Expected semantics bud did not receive any for token %s", jplagType.getDescription())); + } + CodeSemantics semantics = semanticsSupplier.apply(entity); + token = new Token(jplagType, this.file, line, column, length, semantics); + variableRegistry.updateSemantics(semantics); + } else { + if (semanticsSupplier != null) { + logger.warning(() -> String.format("Received semantics for token %s despite not expecting any", jplagType.getDescription())); + } + token = new Token(jplagType, this.file, line, column, length); + } + addToken(token); + } + + void enterFile(File newFile) { + this.file = newFile; + } + + void addFileEndToken() { + addToken(extractsSemantics ? Token.semanticFileEnd(file) : Token.fileEnd(file)); + // don't need to update semantics because variable registry is new for every file + } + + private void addToken(Token token) { + this.collected.add(token); + } +} diff --git a/language-antlr-utils/src/test/antlr4/de/jplag/antlr/TestLexer.g4 b/language-antlr-utils/src/test/antlr4/de/jplag/antlr/TestLexer.g4 new file mode 100644 index 000000000..e6611d509 --- /dev/null +++ b/language-antlr-utils/src/test/antlr4/de/jplag/antlr/TestLexer.g4 @@ -0,0 +1,14 @@ +lexer grammar TestLexer; + +BRACKET_OPEN: '('; +BRACKET_CLOSE: ')'; +PLUS: '+'; +MINUS: '-'; + +NUMBER: ('0'..'9')+; +VAR_NAME: ('a'..'z')+; +VAR_SEPARATOR: ','; + +LINEBREAK: ('\n' | '\r\n'); + +WHITESPACE: ' '+; \ No newline at end of file diff --git a/language-antlr-utils/src/test/antlr4/de/jplag/antlr/TestParser.g4 b/language-antlr-utils/src/test/antlr4/de/jplag/antlr/TestParser.g4 new file mode 100644 index 000000000..1e455b73a --- /dev/null +++ b/language-antlr-utils/src/test/antlr4/de/jplag/antlr/TestParser.g4 @@ -0,0 +1,40 @@ +parser grammar TestParser; + +options { tokenVocab = TestLexer; } + +expressionFile + : varDefs? calcExpression EOF + | varDefs? subExpression EOF + ; + +varDefs + : (varDef VAR_SEPARATOR)* varDef LINEBREAK + ; + +varDef + : VAR_NAME + ; + +subExpression + : BRACKET_OPEN calcExpression BRACKET_CLOSE + ; + +calcExpression + : subExpression operator subExpression + | calcExpression operator calcExpression + | calcExpression operator subExpression + | subExpression operator calcExpression + | WHITESPACE calcExpression + | calcExpression WHITESPACE + | NUMBER + | varRef + ; + +varRef + : VAR_NAME + ; + +operator + : PLUS + | MINUS + ; \ No newline at end of file diff --git a/language-antlr-utils/src/test/java/de/jplag/antlr/LanguageTest.java b/language-antlr-utils/src/test/java/de/jplag/antlr/LanguageTest.java new file mode 100644 index 000000000..81941ac8d --- /dev/null +++ b/language-antlr-utils/src/test/java/de/jplag/antlr/LanguageTest.java @@ -0,0 +1,66 @@ +package de.jplag.antlr; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.io.File; +import java.util.Set; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import de.jplag.ParsingException; +import de.jplag.antlr.testLanguage.TestLanguage; +import de.jplag.antlr.testLanguage.TestParserAdapter; + +/** + * Some tests for the abstract antlr language + */ +class LanguageTest { + @Test + void testExceptionForNoDefinedParser() { + LanguageWithoutParser lang = new LanguageWithoutParser(); + Set emptySet = Set.of(); + assertThrows(UnsupportedOperationException.class, () -> lang.parse(emptySet)); + } + + @Test + void testLanguageWithStaticParser() throws ParsingException { + TestLanguage lang = new TestLanguage(); + Assertions.assertEquals(0, lang.parse(Set.of()).size()); + } + + @Test + void testLanguageWithLazyParser() throws ParsingException { + LanguageWithLazyParser lang = new LanguageWithLazyParser(); + Assertions.assertEquals(0, lang.parse(Set.of()).size()); + } + + private static class LanguageWithoutParser extends AbstractAntlrLanguage { + @Override + public String[] suffixes() { + return new String[0]; + } + + @Override + public String getName() { + return null; + } + + @Override + public String getIdentifier() { + return null; + } + + @Override + public int minimumTokenMatch() { + return 0; + } + } + + private static class LanguageWithLazyParser extends LanguageWithoutParser { + @Override + protected AbstractAntlrParserAdapter initializeParser() { + return new TestParserAdapter(); + } + } +} diff --git a/language-antlr-utils/src/test/java/de/jplag/antlr/ParserTest.java b/language-antlr-utils/src/test/java/de/jplag/antlr/ParserTest.java new file mode 100644 index 000000000..e33277201 --- /dev/null +++ b/language-antlr-utils/src/test/java/de/jplag/antlr/ParserTest.java @@ -0,0 +1,29 @@ +package de.jplag.antlr; + +import static de.jplag.antlr.testLanguage.TestTokenType.*; + +import de.jplag.antlr.testLanguage.TestLanguage; +import de.jplag.antlr.testLanguage.TestTokenType; +import de.jplag.testutils.LanguageModuleTest; +import de.jplag.testutils.datacollector.TestDataCollector; +import de.jplag.testutils.datacollector.TestSourceIgnoredLinesCollector; + +public class ParserTest extends LanguageModuleTest { + public ParserTest() { + super(new TestLanguage(), TestTokenType.class); + } + + @Override + protected void collectTestData(TestDataCollector collector) { + collector.inlineSource("(1 + 3)").testTokenSequence(SUB_EXPRESSION_BEGIN, ADDITION, NUMBER, NUMBER, SUB_EXPRESSION_END); + + collector.inlineSource("(1 - 3)").testTokenSequence(SUB_EXPRESSION_BEGIN, NUMBER, SUBTRACTION, NUMBER, SUB_EXPRESSION_END); + + collector.inlineSource("1").testTokenSequence(NUMBER); + } + + @Override + protected void configureIgnoredLines(TestSourceIgnoredLinesCollector collector) { + + } +} diff --git a/language-antlr-utils/src/test/java/de/jplag/antlr/testLanguage/TestLanguage.java b/language-antlr-utils/src/test/java/de/jplag/antlr/testLanguage/TestLanguage.java new file mode 100644 index 000000000..63a5f0d07 --- /dev/null +++ b/language-antlr-utils/src/test/java/de/jplag/antlr/testLanguage/TestLanguage.java @@ -0,0 +1,32 @@ +package de.jplag.antlr.testLanguage; + +import de.jplag.antlr.AbstractAntlrLanguage; + +public class TestLanguage extends AbstractAntlrLanguage { + /** + * New instance + */ + public TestLanguage() { + super(new TestParserAdapter()); + } + + @Override + public String[] suffixes() { + return new String[] {"expression"}; + } + + @Override + public String getName() { + return "test"; + } + + @Override + public String getIdentifier() { + return "test"; + } + + @Override + public int minimumTokenMatch() { + return 8; + } +} diff --git a/language-antlr-utils/src/test/java/de/jplag/antlr/testLanguage/TestListener.java b/language-antlr-utils/src/test/java/de/jplag/antlr/testLanguage/TestListener.java new file mode 100644 index 000000000..9073ad954 --- /dev/null +++ b/language-antlr-utils/src/test/java/de/jplag/antlr/testLanguage/TestListener.java @@ -0,0 +1,21 @@ +package de.jplag.antlr.testLanguage; + +import static de.jplag.antlr.testLanguage.TestTokenType.*; + +import de.jplag.antlr.*; +import de.jplag.antlr.TestParser.*; +import de.jplag.semantics.CodeSemantics; +import de.jplag.semantics.VariableScope; + +class TestListener extends AbstractAntlrListener { + + TestListener() { + visit(VarDefContext.class).map(VARDEF).withSemantics(CodeSemantics::createKeep) + .onEnter((rule, variableRegistry) -> variableRegistry.registerVariable(rule.VAR_NAME().getText(), VariableScope.FILE, false)); + visit(CalcExpressionContext.class, rule -> rule.operator() != null && rule.operator().PLUS() != null).map(ADDITION).withControlSemantics(); + visit(OperatorContext.class, rule -> rule.MINUS() != null).map(SUBTRACTION).withControlSemantics(); + visit(SubExpressionContext.class).map(SUB_EXPRESSION_BEGIN, SUB_EXPRESSION_END).addLocalScope().withControlSemantics(); + visit(TestParser.NUMBER).map(NUMBER).withSemantics(CodeSemantics::createKeep); + visit(VarDefContext.class).map(VARDEF).withSemantics(CodeSemantics::createKeep); + } +} diff --git a/language-antlr-utils/src/test/java/de/jplag/antlr/testLanguage/TestParserAdapter.java b/language-antlr-utils/src/test/java/de/jplag/antlr/testLanguage/TestParserAdapter.java new file mode 100644 index 000000000..c2873a167 --- /dev/null +++ b/language-antlr-utils/src/test/java/de/jplag/antlr/testLanguage/TestParserAdapter.java @@ -0,0 +1,32 @@ +package de.jplag.antlr.testLanguage; + +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.ParserRuleContext; + +import de.jplag.antlr.*; + +public class TestParserAdapter extends AbstractAntlrParserAdapter { + private static final TestListener listener = new TestListener(); + + @Override + protected Lexer createLexer(CharStream input) { + return new TestLexer(input); + } + + @Override + protected TestParser createParser(CommonTokenStream tokenStream) { + return new TestParser(tokenStream); + } + + @Override + protected ParserRuleContext getEntryContext(TestParser parser) { + return parser.expressionFile(); + } + + @Override + protected AbstractAntlrListener getListener() { + return listener; + } +} diff --git a/language-antlr-utils/src/test/java/de/jplag/antlr/testLanguage/TestTokenType.java b/language-antlr-utils/src/test/java/de/jplag/antlr/testLanguage/TestTokenType.java new file mode 100644 index 000000000..33dc207f2 --- /dev/null +++ b/language-antlr-utils/src/test/java/de/jplag/antlr/testLanguage/TestTokenType.java @@ -0,0 +1,24 @@ +package de.jplag.antlr.testLanguage; + +import de.jplag.TokenType; + +public enum TestTokenType implements TokenType { + ADDITION("PLUS("), + SUBTRACTION("MINUS("), + SUB_EXPRESSION_BEGIN("SUB {"), + SUB_EXPRESSION_END("} SUB"), + NUMBER("NUM"), + VARDEF("VARDEF"), + VARREF("VARREF"); + + private final String description; + + TestTokenType(String description) { + this.description = description; + } + + @Override + public String getDescription() { + return description; + } +} diff --git a/language-api/pom.xml b/language-api/pom.xml index 2476d5e21..27585b2bf 100644 --- a/language-api/pom.xml +++ b/language-api/pom.xml @@ -15,5 +15,10 @@ org.kohsuke.metainf-services metainf-services + + com.ibm.icu + icu4j-charset + 73.2 + diff --git a/language-api/src/main/java/de/jplag/Language.java b/language-api/src/main/java/de/jplag/Language.java index 4f4d94d78..c7e199667 100644 --- a/language-api/src/main/java/de/jplag/Language.java +++ b/language-api/src/main/java/de/jplag/Language.java @@ -4,6 +4,8 @@ import java.util.List; import java.util.Set; +import de.jplag.options.LanguageOptions; + /** * Common interface for all languages. Each language-front end must provide a concrete language implementation. */ @@ -37,6 +39,14 @@ public interface Language { */ List parse(Set files) throws ParsingException; + /** + * Indicates whether the tokens returned by parse have semantic information added to them, i.e. whether the token + * attribute semantics is null or not. + */ + default boolean tokensHaveSemantics() { + return false; + } + /** * Determines whether a fixed-width font should be used to display that language. */ @@ -58,4 +68,29 @@ default boolean useViewFiles() { default String viewFileSuffix() { return ""; } + + /** + * Returns a new option object for the language. + * @return The options + */ + default LanguageOptions getOptions() { + return LanguageOptions.EMPTY_OPTIONS; + } + + /** + * Specifies if the submission order is relevant for this language. + * @return defaults to false. + */ + default boolean expectsSubmissionOrder() { + return false; + } + + /** + * Re-orders the provided submission according the requirements of the language. + * @param submissions is the list of submissions. + * @return the re-ordered list. + */ + default List customizeSubmissionOrder(List submissions) { + return submissions; + } } diff --git a/language-api/src/main/java/de/jplag/SharedTokenType.java b/language-api/src/main/java/de/jplag/SharedTokenType.java index 5374114ec..6866f46a2 100644 --- a/language-api/src/main/java/de/jplag/SharedTokenType.java +++ b/language-api/src/main/java/de/jplag/SharedTokenType.java @@ -11,6 +11,7 @@ public enum SharedTokenType implements TokenType { private final String description; + @Override public String getDescription() { return description; } diff --git a/language-api/src/main/java/de/jplag/Token.java b/language-api/src/main/java/de/jplag/Token.java index 508efb206..b279b886d 100644 --- a/language-api/src/main/java/de/jplag/Token.java +++ b/language-api/src/main/java/de/jplag/Token.java @@ -5,6 +5,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import de.jplag.semantics.CodeSemantics; + /** * This class represents a token in a source code. It can represent keywords, identifiers, syntactical structures etc. * What types of tokens there are depends on the specific language, meaning JPlag does not enforce a specific token set. @@ -20,14 +22,7 @@ public class Token { private int length; private File file; private TokenType type; - - /** - * Creates a token of type {@link SharedTokenType#FILE_END FILE_END} without information about line, column, and length. - * @param file is the name of the source code file. - */ - public static Token fileEnd(File file) { - return new Token(SharedTokenType.FILE_END, file, NO_VALUE, NO_VALUE, NO_VALUE); - } + private CodeSemantics semantics; // value null if no semantics /** * Creates a token with column and length information. @@ -51,6 +46,48 @@ public Token(TokenType type, File file, int line, int column, int length) { this.length = length; } + /** + * Creates a token with column and length information. + * @param type is the token type. + * @param file is the name of the source code file. + * @param trace is the tracing information of the token, meaning line, column, and length. + */ + public Token(TokenType type, File file, TokenTrace trace) { + this(type, file, trace.line(), trace.column(), trace.length()); + } + + /** + * Creates a token with column, length and semantic information. + * @param type is the token type. + * @param file is the name of the source code file. + * @param line is the line index in the source code where the token resides. Index is 1-based. + * @param column is the column index, meaning where the token starts in the line. Index is 1-based. + * @param length is the length of the token in the source code. + * @param semantics is a record containing semantic information about the token. + */ + public Token(TokenType type, File file, int line, int column, int length, CodeSemantics semantics) { + this(type, file, line, column, length); + this.semantics = semantics; + } + + /** + * Creates a token of type {@link SharedTokenType#FILE_END FILE_END} without information about line, column, and length. + * @param file is the name of the source code file. + */ + public static Token fileEnd(File file) { + return new Token(SharedTokenType.FILE_END, file, NO_VALUE, NO_VALUE, NO_VALUE); + } + + /** + * Creates a token of type {@link SharedTokenType#FILE_END FILE_END} without information about line, column, and length, + * but with semantic information. + * @param file is the name of the source code file. + */ + public static Token semanticFileEnd(File file) { + CodeSemantics semantics = CodeSemantics.createControl(); + return new Token(SharedTokenType.FILE_END, file, NO_VALUE, NO_VALUE, NO_VALUE, semantics); + } + /** * Returns the character index which denotes where the code sections represented by this token starts in the line. * @return the character index in the line. @@ -93,4 +130,11 @@ public TokenType getType() { public String toString() { return type.toString(); } + + /** + * @return the semantics of the token. + */ + public CodeSemantics getSemantics() { + return semantics; + } } diff --git a/language-api/src/main/java/de/jplag/TokenPrinter.java b/language-api/src/main/java/de/jplag/TokenPrinter.java index 5378724c6..fb2198c4b 100644 --- a/language-api/src/main/java/de/jplag/TokenPrinter.java +++ b/language-api/src/main/java/de/jplag/TokenPrinter.java @@ -46,6 +46,15 @@ private TokenPrinter() { // Utility class, no public constructor. } + /** + * Creates a string representation of a set of files line by line and adds the tokens under the lines. + * @param tokens is the list of tokens parsed from the files. + * @return the string representation. + */ + public static String printTokens(List tokens) { + return printTokens(tokens, null); + } + /** * Creates a string representation of a set of files line by line and adds the tokens under the lines. * @param tokens is the list of tokens parsed from the files. @@ -68,7 +77,11 @@ public static String printTokens(List tokenList, File rootDirectory, Opti Map> fileToTokens = groupTokensByFile(tokenList); fileToTokens.forEach((File file, List fileTokens) -> { - builder.append(rootDirectory.toPath().relativize(file.toPath()).toString()); + if (rootDirectory != null) { + builder.append(rootDirectory.toPath().relativize(file.toPath()).toString()); + } else { + builder.append(""); + } List lineDatas = getLineData(fileTokens, suffix); lineDatas.forEach(lineData -> { diff --git a/language-api/src/main/java/de/jplag/TokenTrace.java b/language-api/src/main/java/de/jplag/TokenTrace.java new file mode 100644 index 000000000..6fd9808f8 --- /dev/null +++ b/language-api/src/main/java/de/jplag/TokenTrace.java @@ -0,0 +1,17 @@ +package de.jplag; + +/** + * Tracing information to locate the corresponding code section of a token. + * @param line is the line index in the source code where the token resides. Index is 1-based. + * @param column is the column index, meaning where the token starts in the line. Index is 1-based. + * @param length is the length of the token in the source code. + */ +public record TokenTrace(int line, int column, int length) { + + /** + * Creates a empty trace with line, column, and length set to {@link Token#NO_VALUE NO_VALUE}. + */ + public TokenTrace() { + this(Token.NO_VALUE, Token.NO_VALUE, Token.NO_VALUE); + } +} diff --git a/language-api/src/main/java/de/jplag/options/DefaultLanguageOption.java b/language-api/src/main/java/de/jplag/options/DefaultLanguageOption.java new file mode 100644 index 000000000..001f7c233 --- /dev/null +++ b/language-api/src/main/java/de/jplag/options/DefaultLanguageOption.java @@ -0,0 +1,58 @@ +package de.jplag.options; + +/** + * Default implementation for {@link LanguageOption} + * @param The type of the option + */ +public class DefaultLanguageOption implements LanguageOption { + private final OptionType type; + private final String name; + private final String description; + + private T value; + private boolean hasValue; + + DefaultLanguageOption(OptionType type, String name, String description, T defaultValue) { + this.type = type; + this.name = name; + this.value = defaultValue; + this.description = description; + this.hasValue = true; + } + + DefaultLanguageOption(OptionType type, String description, String name) { + this(type, name, description, null); + this.hasValue = false; + } + + @Override + public OptionType getType() { + return this.type; + } + + @Override + public String getName() { + return this.name; + } + + @Override + public T getValue() { + return this.value; + } + + @Override + public String getDescription() { + return this.description; + } + + @Override + public void setValue(T value) { + this.value = value; + this.hasValue = true; + } + + @Override + public boolean hasValue() { + return this.hasValue; + } +} diff --git a/language-api/src/main/java/de/jplag/options/LanguageOption.java b/language-api/src/main/java/de/jplag/options/LanguageOption.java new file mode 100644 index 000000000..afc6f4da6 --- /dev/null +++ b/language-api/src/main/java/de/jplag/options/LanguageOption.java @@ -0,0 +1,45 @@ +package de.jplag.options; + +/** + * A single language specific option. + * @param The type of the options value + */ +public interface LanguageOption { + /** + * @return The type instance for the option. + */ + OptionType getType(); + + /** + * @return The name of the option. + */ + String getName(); + + /** + * @return The name as a unix parameter name. This should be "--" followed by the value of getName + */ + default String getNameAsUnixParameter() { + return "--" + this.getName(); + } + + /** + * @return The value of the option. + */ + T getValue(); + + /** + * @return The description of the option. + */ + String getDescription(); + + /** + * Updates the options value. + * @param value The new value + */ + void setValue(T value); + + /** + * @return True, if the option has a value right now. The actual value might still be null. + */ + boolean hasValue(); +} diff --git a/language-api/src/main/java/de/jplag/options/LanguageOptions.java b/language-api/src/main/java/de/jplag/options/LanguageOptions.java new file mode 100644 index 000000000..8f0bf2a7e --- /dev/null +++ b/language-api/src/main/java/de/jplag/options/LanguageOptions.java @@ -0,0 +1,81 @@ +package de.jplag.options; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Container for a languages options. Should be implemented per language. + */ +public abstract class LanguageOptions { + public static final LanguageOptions EMPTY_OPTIONS = new LanguageOptions() { + }; + + private final List> options; + + /** + * New instance + */ + protected LanguageOptions() { + this.options = new ArrayList<>(); + } + + /** + * Creates a new option with default value. + * @param type The type + * @param name The name + * @param description the description + * @param defaultValue The default value + * @param The java type + * @return The new option + */ + protected LanguageOption createDefaultOption(OptionType type, String name, String description, T defaultValue) { + LanguageOption option = new DefaultLanguageOption<>(type, name, description, defaultValue); + this.options.add(option); + return option; + } + + /** + * Creates a new option with default value and empty description. + * @param type The type + * @param name The name + * @param defaultValue The default value + * @param The java type + * @return The new option + */ + protected LanguageOption createDefaultOption(OptionType type, String name, T defaultValue) { + return createDefaultOption(type, name, "", defaultValue); + } + + /** + * Creates a new option + * @param type The type + * @param name The name + * @param description The description + * @param The java type + * @return The new option + */ + protected LanguageOption createOption(OptionType type, String name, String description) { + LanguageOption option = new DefaultLanguageOption<>(type, name, description); + this.options.add(option); + return option; + } + + /** + * Creates a new option with empty description + * @param type The type + * @param name The name + * @param The java type + * @return The new option + */ + protected LanguageOption createOption(OptionType type, String name) { + return createOption(type, name, ""); + } + + /** + * @return The list of all options + */ + public List> getOptionsAsList() { + return Collections.unmodifiableList(this.options); + } +} diff --git a/language-api/src/main/java/de/jplag/options/OptionType.java b/language-api/src/main/java/de/jplag/options/OptionType.java new file mode 100644 index 000000000..aaf677370 --- /dev/null +++ b/language-api/src/main/java/de/jplag/options/OptionType.java @@ -0,0 +1,53 @@ +package de.jplag.options; + +/** + * The available types for language specific options. + * @param The java type of the option. + */ +public abstract sealed class OptionType { + static final class StringType extends OptionType { + public static final StringType INSTANCE = new StringType(); + + private StringType() { + super(String.class); + } + } + + static final class IntegerType extends OptionType { + public static final IntegerType INSTANCE = new IntegerType(); + + private IntegerType() { + super(Integer.class); + } + } + + static final class BooleanType extends OptionType { + public static final BooleanType INSTANCE = new BooleanType(); + + private BooleanType() { + super(Boolean.class); + } + } + + public static StringType string() { + return StringType.INSTANCE; + } + + public static IntegerType integer() { + return IntegerType.INSTANCE; + } + + public static BooleanType bool() { + return BooleanType.INSTANCE; + } + + private final Class javaType; + + private OptionType(Class javaType) { + this.javaType = javaType; + } + + public Class getJavaType() { + return javaType; + } +} diff --git a/language-api/src/main/java/de/jplag/semantics/CodeSemantics.java b/language-api/src/main/java/de/jplag/semantics/CodeSemantics.java new file mode 100644 index 000000000..2ef9f0883 --- /dev/null +++ b/language-api/src/main/java/de/jplag/semantics/CodeSemantics.java @@ -0,0 +1,211 @@ +package de.jplag.semantics; + +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +/** + * Contains semantic information about a code snippet, in our case either a token or a statement. + */ +public class CodeSemantics { + + private boolean keep; + private PositionSignificance positionSignificance; + private final int bidirectionalBlockDepthChange; + private Set reads; + private Set writes; + + /** + * Creates new semantics. reads and writes, which each contain the variables which were (potentially) read from/written + * to in this code snippet, are created empty. + * @param keep Whether the code snippet must be kept or if it may be removed. + * @param positionSignificance In which way the position of the code snippet relative to other code snippets of the same + * type is significant. For the possible options see {@link PositionSignificance}. + * @param bidirectionalBlockDepthChange How the code snippet affects the depth of bidirectional blocks, meaning blocks + * where any statement within it may be executed after any other. This will typically be a loop. + * @param reads A set of the variables which were (potentially) read from in the code snippet. + * @param writes A set of the variables which were (potentially) written to in the code snippet. + */ + private CodeSemantics(boolean keep, PositionSignificance positionSignificance, int bidirectionalBlockDepthChange, Set reads, + Set writes) { + this.keep = keep; + this.positionSignificance = positionSignificance; + this.bidirectionalBlockDepthChange = bidirectionalBlockDepthChange; + this.reads = reads; + this.writes = writes; + } + + private CodeSemantics(boolean keep, PositionSignificance positionSignificance, int bidirectionalBlockDepthChange) { + this(keep, positionSignificance, bidirectionalBlockDepthChange, new HashSet<>(), new HashSet<>()); + } + + /** + * Creates new semantics with the following meaning: The code snippet may be removed, and its position relative to other + * code snippets may change. Example: An assignment to a local variable. + */ + public CodeSemantics() { + this(false, PositionSignificance.NONE, 0); + } + + /** + * @return new semantics with the following meaning: The code snippet may not be removed, and its position relative to + * other code snippets may change. Example: An attribute declaration. + */ + public static CodeSemantics createKeep() { + return new CodeSemantics(true, PositionSignificance.NONE, 0); + } + + /** + * @return new semantics with the following meaning: The code snippet may not be removed, and its position must stay + * invariant to other code snippets of the same type. Example: A method call which is guaranteed to not result in an + * exception. + */ + public static CodeSemantics createCritical() { + return new CodeSemantics(true, PositionSignificance.PARTIAL, 0); + } + + /** + * @return new semantics with the following meaning: The code snippet may not be removed, and its position must stay + * invariant to all other code snippets. Example: A return statement. + */ + public static CodeSemantics createControl() { + return new CodeSemantics(true, PositionSignificance.FULL, 0); + } + + /** + * @return new semantics with the following meaning: The code snippet may not be removed, and its position must stay + * invariant to all other code snippets, which also begins a bidirectional block. Example: The beginning of a while + * loop. + */ + public static CodeSemantics createLoopBegin() { + return new CodeSemantics(true, PositionSignificance.FULL, 1); + } + + /** + * @return new semantics with the following meaning: The code snippet may not be removed, and its position must stay + * invariant to all other code snippets, which also ends a bidirectional block. Example: The end of a while loop. + */ + public static CodeSemantics createLoopEnd() { + return new CodeSemantics(true, PositionSignificance.FULL, -1); + } + + /** + * @return whether this code snippet must be kept. + */ + public boolean keep() { + return keep; + } + + /** + * Mark this code snippet as having to be kept. + */ + public void markKeep() { + keep = true; + } + + /** + * @return the change this code snippet causes in the depth of bidirectional loops. + */ + public int bidirectionalBlockDepthChange() { + return bidirectionalBlockDepthChange; + } + + /** + * @return whether this code snippet has partial position significance. + */ + public boolean hasPartialPositionSignificance() { + return positionSignificance == PositionSignificance.PARTIAL; + } + + /** + * @return whether this code snippet has full position significance. + */ + public boolean hasFullPositionSignificance() { + return positionSignificance == PositionSignificance.FULL; + } + + /** + * Mark this code snippet as having full position significance. + */ + public void markFullPositionSignificance() { + positionSignificance = PositionSignificance.FULL; + } + + /** + * @return an unmodifiable set of the variables which were (potentially) read from in this code snippet. + */ + public Set reads() { + return Collections.unmodifiableSet(reads); + } + + /** + * @return an unmodifiable set of the variables which were (potentially) written to in this code snippet. + */ + public Set writes() { + return Collections.unmodifiableSet(writes); + } + + /** + * Add a variable to the set of variables which were (potentially) read from in this code snippet. + * @param variable The variable which is added. + */ + public void addRead(Variable variable) { + reads.add(variable); + } + + /** + * Add a variable to the set of variables which were (potentially) written to in this code snippet. + * @param variable The variable which is added. + */ + public void addWrite(Variable variable) { + writes.add(variable); + } + + /** + * Create new joint semantics by joining a number of existing ones. It has the following properties: + *

    + *
  • keep is the disjunction of all keeps
  • + *
  • position significance is the most significant
  • + *
  • bidirectionalBlockDepthChange is the sum of all bidirectionalBlockDepthChanges
  • + *
  • reads is the union of all reads
  • + *
  • writes is the union of all writes
  • + *
+ * @param semanticsList A list of the semantics which should be joined. + * @return New semantics which were created by joining the elements in the semanticsList. + */ + public static CodeSemantics join(List semanticsList) { + boolean keep = false; + PositionSignificance positionSignificance = PositionSignificance.NONE; + int bidirectionalBlockDepthChange = 0; + Set reads = new HashSet<>(); + Set writes = new HashSet<>(); + for (CodeSemantics semantics : semanticsList) { + keep = keep || semantics.keep; + if (semantics.positionSignificance.compareTo(positionSignificance) > 0) { + positionSignificance = semantics.positionSignificance; + } + bidirectionalBlockDepthChange += semantics.bidirectionalBlockDepthChange(); + reads.addAll(semantics.reads); + writes.addAll(semantics.writes); + } + return new CodeSemantics(keep, positionSignificance, bidirectionalBlockDepthChange, reads, writes); + } + + @Override + public String toString() { + List properties = new LinkedList<>(); + if (keep) + properties.add("keep"); + if (positionSignificance != PositionSignificance.NONE) + properties.add(positionSignificance.name().toLowerCase() + " position significance"); + if (bidirectionalBlockDepthChange != 0) + properties.add("change bidirectional block depth by " + bidirectionalBlockDepthChange); + if (!reads.isEmpty()) + properties.add("read " + String.join(" ", reads.stream().map(Variable::toString).toList())); + if (!writes.isEmpty()) + properties.add("write " + String.join(" ", writes.stream().map(Variable::toString).toList())); + return String.join(", ", properties); + } +} \ No newline at end of file diff --git a/language-api/src/main/java/de/jplag/semantics/PositionSignificance.java b/language-api/src/main/java/de/jplag/semantics/PositionSignificance.java new file mode 100644 index 000000000..b4a6a4ccc --- /dev/null +++ b/language-api/src/main/java/de/jplag/semantics/PositionSignificance.java @@ -0,0 +1,19 @@ +package de.jplag.semantics; + +/** + * Enumerates how the position of an item in a sequence relative to other items may be significant. + */ +enum PositionSignificance { + /** + * The position of the item relative to other items is insignificant. + */ + NONE, + /** + * The position of the item relative to other items with partial position significance is significant. + */ + PARTIAL, + /** + * The position of the item to all other items is significant. + */ + FULL +} diff --git a/language-api/src/main/java/de/jplag/semantics/Variable.java b/language-api/src/main/java/de/jplag/semantics/Variable.java new file mode 100644 index 000000000..bf1588a93 --- /dev/null +++ b/language-api/src/main/java/de/jplag/semantics/Variable.java @@ -0,0 +1,25 @@ +package de.jplag.semantics; + +/** + * Each variable has its unique identity, important for tracing in graph (NormalizationGraph::spreadKeep). + */ +public class Variable { + private final String name; + private final VariableScope scope; + private final boolean isMutable; + + Variable(String name, VariableScope scope, boolean isMutable) { + this.name = name; + this.scope = scope; + this.isMutable = isMutable; + } + + boolean isMutable() { + return isMutable; + } + + @Override + public String toString() { + return name + (isMutable ? "*" : "") + " [scope: " + scope.name().toLowerCase() + "]"; + } +} diff --git a/language-api/src/main/java/de/jplag/semantics/VariableAccessType.java b/language-api/src/main/java/de/jplag/semantics/VariableAccessType.java new file mode 100644 index 000000000..9829050fb --- /dev/null +++ b/language-api/src/main/java/de/jplag/semantics/VariableAccessType.java @@ -0,0 +1,27 @@ +package de.jplag.semantics; + +/** + * The ways a variable can be accessed. + */ +public enum VariableAccessType { + /** + * The variable is read from. + */ + READ(true, false), + /** + * The variable is written to. + */ + WRITE(false, true), + /** + * The variable is read from and written to. + */ + READ_WRITE(true, true); + + final boolean isRead; + final boolean isWrite; + + VariableAccessType(boolean isRead, boolean isWrite) { + this.isRead = isRead; + this.isWrite = isWrite; + } +} diff --git a/language-api/src/main/java/de/jplag/semantics/VariableRegistry.java b/language-api/src/main/java/de/jplag/semantics/VariableRegistry.java new file mode 100644 index 000000000..dfe8df0bf --- /dev/null +++ b/language-api/src/main/java/de/jplag/semantics/VariableRegistry.java @@ -0,0 +1,172 @@ +package de.jplag.semantics; + +import java.util.Deque; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Map; +import java.util.Set; + +/** + * Registry of variables to assist in generating token semantics. + */ +public class VariableRegistry { + private CodeSemantics semantics; + private Map fileVariables; + private Deque> classVariables; // map class name to map of variable names to variables + private Map> localVariables; // map local variable name to stack of variables + private Deque> localVariablesByScope; // stack of local variable names in scope + private VariableAccessType nextVariableAccessType; + private boolean ignoreNextVariableAccess; + private boolean mutableWrite; + + /** + * Initialize a new variable registry. + */ + public VariableRegistry() { + this.fileVariables = new HashMap<>(); + this.classVariables = new LinkedList<>(); + this.localVariables = new HashMap<>(); + this.localVariablesByScope = new LinkedList<>(); + this.nextVariableAccessType = VariableAccessType.READ; // the default + this.ignoreNextVariableAccess = false; + this.mutableWrite = false; + } + + /** + * @return If we are currently in a local scope. + */ + public boolean inLocalScope() { + return !localVariablesByScope.isEmpty(); + } + + /** + * Set the type of the next variable access. This only influences the very next call of registerVariableOperation. + * @param nextVariableAccessType The type of the next variable access. + */ + public void setNextVariableAccessType(VariableAccessType nextVariableAccessType) { + this.nextVariableAccessType = nextVariableAccessType; + } + + /** + * Set whether the next variable access is ignored. This only influences the very next call of + * registerVariableOperation. + * @param ignoreNextVariableAccess Whether the next variable access is ignored. + */ + public void setIgnoreNextVariableAccess(boolean ignoreNextVariableAccess) { + this.ignoreNextVariableAccess = ignoreNextVariableAccess; + } + + /** + * Set whether accesses to mutable variables are writes from this point on. + * @param mutableWrite Whether accesses to mutable variables are writes from this point on. + */ + public void setMutableWrite(boolean mutableWrite) { + this.mutableWrite = mutableWrite; + } + + /** + * Enter a class. + */ + public void enterClass() { + classVariables.push(new HashMap<>()); + } + + /** + * Exit a class. This causes all variables bound to the current class to no longer be visible. + */ + public void exitClass() { + classVariables.pop(); + } + + /** + * Enter a local scope. + */ + public void enterLocalScope() { + localVariablesByScope.push(new HashSet<>()); + } + + /** + * Exit a local scope. This causes all variables bound to the current local scope to no longer be visible. + */ + public void exitLocalScope() { + for (String variableName : localVariablesByScope.pop()) { + Deque variableStack = localVariables.get(variableName); + variableStack.pop(); + if (variableStack.isEmpty()) + localVariables.remove(variableName); + } + } + + /** + * Update the current semantics. + * @param semantics are the new current semantics. + */ + public void updateSemantics(CodeSemantics semantics) { + this.semantics = semantics; + } + + /** + * Register a variable. + * @param variableName The variable's name. + * @param scope The variable's scope. + * @param mutable Whether the variable is mutable. + */ + public void registerVariable(String variableName, VariableScope scope, boolean mutable) { + Variable variable = new Variable(variableName, scope, mutable); + switch (scope) { + case FILE -> fileVariables.put(variableName, variable); + case CLASS -> classVariables.getFirst().put(variableName, variable); + case LOCAL -> { + localVariables.putIfAbsent(variableName, new LinkedList<>()); + localVariables.get(variableName).push(variable); + localVariablesByScope.getFirst().add(variableName); + } + } + } + + /** + * Register a variable access, more precisely: Add a variable access to the current CodeSemantics instance. The type of + * the access can be set with setNextVariableAccessType. By default, its type is read. + * @param variableName The variable's name. + * @param isClassVariable Whether the variable is a class variable. This is true if a variable is qualified with the + * "this" keyword in Java, for example. + */ + public void registerVariableAccess(String variableName, boolean isClassVariable) { + if (ignoreNextVariableAccess) { + ignoreNextVariableAccess = false; + return; + } + Variable variable = isClassVariable ? getClassVariable(variableName) : getVariable(variableName); + if (variable != null) { + if (nextVariableAccessType.isRead) + semantics.addRead(variable); + if (nextVariableAccessType.isWrite || (mutableWrite && variable.isMutable())) + semantics.addWrite(variable); + } // track global variables here through else + nextVariableAccessType = VariableAccessType.READ; + } + + /** + * Add all non-local visible variables as reads to the current CodeSemantics instance. + */ + public void addAllNonLocalVariablesAsReads() { + Set nonLocalVariables = new HashSet<>(fileVariables.values()); + nonLocalVariables.addAll(classVariables.getFirst().values()); + for (Variable variable : nonLocalVariables) + semantics.addRead(variable); + } + + private Variable getVariable(String variableName) { + Deque variableIdStack = localVariables.get(variableName); + if (variableIdStack != null) + return variableIdStack.getFirst(); // stack is never empty + Variable variable = getClassVariable(variableName); + return variable != null ? variable : fileVariables.get(variableName); + } + + private Variable getClassVariable(String variableName) { + Map currentClassVariables = classVariables.peek(); + return currentClassVariables != null ? currentClassVariables.get(variableName) : null; + } +} diff --git a/language-api/src/main/java/de/jplag/semantics/VariableScope.java b/language-api/src/main/java/de/jplag/semantics/VariableScope.java new file mode 100644 index 000000000..8f86407a8 --- /dev/null +++ b/language-api/src/main/java/de/jplag/semantics/VariableScope.java @@ -0,0 +1,19 @@ +package de.jplag.semantics; + +/** + * The scopes a variable can have. Scopes dictate a variable's visibility. + */ +public enum VariableScope { + /** + * The variable is visible in the entire file. + */ + FILE, + /** + * The variable is only visible in the class it was declared in. + */ + CLASS, + /** + * The variable is only visible in the local scope it was declared in. + */ + LOCAL +} diff --git a/language-api/src/main/java/de/jplag/util/FileUtils.java b/language-api/src/main/java/de/jplag/util/FileUtils.java new file mode 100644 index 000000000..37cb84ec9 --- /dev/null +++ b/language-api/src/main/java/de/jplag/util/FileUtils.java @@ -0,0 +1,166 @@ +package de.jplag.util; + +import java.io.*; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; + +import de.jplag.ParsingException; + +import com.ibm.icu.text.CharsetDetector; +import com.ibm.icu.text.CharsetMatch; + +/** + * Encapsulates various interactions with files to prevent issues with file encodings. + */ +public class FileUtils { + private static final Charset DEFAULT_OUTPUT_CHARSET = StandardCharsets.UTF_8; + private static final char BYTE_ORDER_MARK = '\uFEFF'; + private static final int SINGLE_CHAR_BUFFER_SIZE = 10; + + private FileUtils() { + } + + /** + * Opens a file reader, guessing the charset from the content. Also, if the file is encoded in a UTF* encoding and a bom + * exists, it is removed from the reader. + * @param file The file to open for read + * @return The reader, configured with the best matching charset + * @throws IOException If the file does not exist for is not readable + */ + public static BufferedReader openFileReader(File file) throws IOException { + InputStream stream = new BufferedInputStream(new FileInputStream(file)); + Charset charset = detectCharset(stream); + BufferedReader reader = new BufferedReader(new FileReader(file, charset)); + removeBom(reader, charset); + return reader; + } + + /** + * Reads the contents of a file into a single string. + * @param file The file to read + * @return The files content as a string + * @throws IOException If an IO error occurs + * @see FileUtils#openFileReader(File) + */ + public static String readFileContent(File file) throws IOException { + try (BufferedReader reader = openFileReader(file)) { + return reader.lines().collect(Collectors.joining(System.lineSeparator())); + } + } + + /** + * Removes the byte order mark from the beginning of the stream, if it exists and the charset is a UTF* charset. For + * details see: Wikipedia + * @param reader The reader to remove the bom from + * @throws IOException If an IO error occurs. + */ + private static void removeBom(BufferedReader reader, Charset charset) throws IOException { + if (charset.name().toUpperCase().startsWith("UTF")) { + reader.mark(SINGLE_CHAR_BUFFER_SIZE); + if (reader.read() != BYTE_ORDER_MARK) { + reader.reset(); + } + } + } + + /** + * Detects the charset of a file. Prefer using {@link #openFileReader(File)} or {@link #readFileContent(File)} if you + * are only interested in the content. + * @param file The file to detect + * @return The most probable charset + * @throws IOException If an IO error occurs + */ + public static Charset detectCharset(File file) throws IOException { + try (InputStream stream = new BufferedInputStream(new FileInputStream((file)))) { + return detectCharset(stream); + } + } + + /** + * Detects the most probable charset over the whole set of files. + * @param files The files to check + * @return The most probable charset + */ + public static Charset detectCharsetFromMultiple(Collection files) throws ParsingException { + Map> charsetValues = new HashMap<>(); + + List matchData = new ArrayList<>(); + for (File file : files) { + try (InputStream stream = new BufferedInputStream(new FileInputStream(file))) { + matchData.add(detectAllCharsets(stream)); + } catch (IOException e) { + throw new ParsingException(file, e); + } + } + + for (CharsetMatch[] matches : matchData) { + Set remaining = new HashSet<>(Set.of(CharsetDetector.getAllDetectableCharsets())); + for (CharsetMatch match : matches) { + charsetValues.putIfAbsent(match.getName(), new ArrayList<>()); + charsetValues.get(match.getName()).add(match.getConfidence()); + remaining.remove(match.getName()); + } + remaining.forEach(it -> { + charsetValues.putIfAbsent(it, new ArrayList<>()); + charsetValues.get(it).add(0); + }); + } + + AtomicReference mostProbable = new AtomicReference<>(StandardCharsets.UTF_8); + AtomicReference mostProbableConfidence = new AtomicReference<>(0.0); + charsetValues.forEach((charset, confidenceValues) -> { + double average = confidenceValues.stream().mapToInt(it -> it).average().orElse(0); + if (confidenceValues.stream().anyMatch(it -> it == 0)) { + average = 0; + } + if (average > mostProbableConfidence.get()) { + mostProbable.set(Charset.forName(charset)); + mostProbableConfidence.set(average); + } + }); + + return mostProbable.get(); + } + + private static Charset detectCharset(InputStream stream) throws IOException { + CharsetDetector charsetDetector = new CharsetDetector(); + + charsetDetector.setText(stream); + + CharsetMatch match = charsetDetector.detect(); + return Charset.forName(match.getName()); + } + + private static CharsetMatch[] detectAllCharsets(InputStream stream) throws IOException { + CharsetDetector charsetDetector = new CharsetDetector(); + + charsetDetector.setText(stream); + + return charsetDetector.detectAll(); + } + + /** + * Opens a file writer, using the default charset for JPlag + * @param file The file to write + * @return The file writer, configured with the default charset + * @throws IOException If the file does not exist or is not writable + */ + public static Writer openFileWriter(File file) throws IOException { + return new BufferedWriter(new FileWriter(file, DEFAULT_OUTPUT_CHARSET)); + } + + /** + * Writes the given content into the given file using the default charset + * @param file The file + * @param content The content + * @throws IOException If any error occurs + */ + public static void write(File file, String content) throws IOException { + Writer writer = openFileWriter(file); + writer.write(content); + writer.close(); + } +} diff --git a/language-api/src/test/java/de/jplag/TokenPrinterTest.java b/language-api/src/test/java/de/jplag/TokenPrinterTest.java index 4cb1bda1d..11c9c33f3 100644 --- a/language-api/src/test/java/de/jplag/TokenPrinterTest.java +++ b/language-api/src/test/java/de/jplag/TokenPrinterTest.java @@ -103,6 +103,7 @@ private enum TestTokenType implements TokenType { private final String description; + @Override public String getDescription() { return description; } diff --git a/language-api/src/test/java/de/jplag/util/FileUtilTest.java b/language-api/src/test/java/de/jplag/util/FileUtilTest.java new file mode 100644 index 000000000..070b71625 --- /dev/null +++ b/language-api/src/test/java/de/jplag/util/FileUtilTest.java @@ -0,0 +1,48 @@ +package de.jplag.util; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.util.Set; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import de.jplag.ParsingException; + +public class FileUtilTest { + private static final Path TEST_FILE_LOCATION = Path.of("src", "test", "resources", "de", "jplag", "fileReaderTests"); + private static final Path TEST_FILE_SET_LOCATION = Path.of("src", "test", "resources", "de", "jplag", "fileSetEncoding"); + + private static final String expectedFileContent = "Some ascii characters and some others: รค#+รถรผ%&(/)?=?"; + + @ParameterizedTest + @MethodSource("searchTestFiles") + void testReadFile(File file) throws IOException { + String found = FileUtils.readFileContent(file); + + Assertions.assertEquals(expectedFileContent, found, "File contains unexpected content: " + file.getAbsolutePath()); + } + + @ParameterizedTest + @MethodSource("searchTestFiles") + void testCharsetDetection(File file) throws IOException { + Assertions.assertEquals(Charset.forName(file.getName()), FileUtils.detectCharset(file), + "Wrong charset assumed for: " + file.getAbsolutePath()); + } + + @Test + void testDetectFromFileSet() throws ParsingException { + Set files = Set.of(TEST_FILE_SET_LOCATION.toFile().listFiles()); + Charset encoding = FileUtils.detectCharsetFromMultiple(files); + Assertions.assertEquals(StandardCharsets.ISO_8859_1, encoding); + } + + public static File[] searchTestFiles() { + return TEST_FILE_LOCATION.toFile().listFiles(); + } +} diff --git a/language-api/src/test/resources/de/jplag/fileReaderTests/ISO-8859-1 b/language-api/src/test/resources/de/jplag/fileReaderTests/ISO-8859-1 new file mode 100644 index 000000000..292674145 --- /dev/null +++ b/language-api/src/test/resources/de/jplag/fileReaderTests/ISO-8859-1 @@ -0,0 +1 @@ +Some ascii characters and some others: ไ#+๖%&(/)?=? \ No newline at end of file diff --git a/language-api/src/test/resources/de/jplag/fileReaderTests/UTF-16LE b/language-api/src/test/resources/de/jplag/fileReaderTests/UTF-16LE new file mode 100644 index 000000000..642cfe74c Binary files /dev/null and b/language-api/src/test/resources/de/jplag/fileReaderTests/UTF-16LE differ diff --git a/language-api/src/test/resources/de/jplag/fileReaderTests/UTF-32BE b/language-api/src/test/resources/de/jplag/fileReaderTests/UTF-32BE new file mode 100644 index 000000000..f3cd32424 Binary files /dev/null and b/language-api/src/test/resources/de/jplag/fileReaderTests/UTF-32BE differ diff --git a/language-api/src/test/resources/de/jplag/fileReaderTests/UTF-8 b/language-api/src/test/resources/de/jplag/fileReaderTests/UTF-8 new file mode 100644 index 000000000..41e017bde --- /dev/null +++ b/language-api/src/test/resources/de/jplag/fileReaderTests/UTF-8 @@ -0,0 +1 @@ +Some ascii characters and some others: รค#+รถรผ%&(/)?=? \ No newline at end of file diff --git a/language-api/src/test/resources/de/jplag/fileSetEncoding/ascii1 b/language-api/src/test/resources/de/jplag/fileSetEncoding/ascii1 new file mode 100644 index 000000000..4d039c8df --- /dev/null +++ b/language-api/src/test/resources/de/jplag/fileSetEncoding/ascii1 @@ -0,0 +1 @@ +some simple ascii characters \ No newline at end of file diff --git a/language-api/src/test/resources/de/jplag/fileSetEncoding/ascii2 b/language-api/src/test/resources/de/jplag/fileSetEncoding/ascii2 new file mode 100644 index 000000000..72af43005 --- /dev/null +++ b/language-api/src/test/resources/de/jplag/fileSetEncoding/ascii2 @@ -0,0 +1 @@ +some more ascii characters \ No newline at end of file diff --git a/language-api/src/test/resources/de/jplag/fileSetEncoding/notAscii b/language-api/src/test/resources/de/jplag/fileSetEncoding/notAscii new file mode 100644 index 000000000..3cfd99b9d --- /dev/null +++ b/language-api/src/test/resources/de/jplag/fileSetEncoding/notAscii @@ -0,0 +1 @@ +this contains a non ascii character: ไ diff --git a/language-testutils/src/test/java/de/jplag/testutils/LanguageModuleTest.java b/language-testutils/src/test/java/de/jplag/testutils/LanguageModuleTest.java new file mode 100644 index 000000000..46133a743 --- /dev/null +++ b/language-testutils/src/test/java/de/jplag/testutils/LanguageModuleTest.java @@ -0,0 +1,296 @@ +package de.jplag.testutils; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertIterableEquals; +import static org.junit.jupiter.api.Assertions.assertLinesMatch; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import de.jplag.Language; +import de.jplag.ParsingException; +import de.jplag.SharedTokenType; +import de.jplag.Token; +import de.jplag.TokenPrinter; +import de.jplag.TokenType; +import de.jplag.testutils.datacollector.TestData; +import de.jplag.testutils.datacollector.TestDataCollector; +import de.jplag.testutils.datacollector.TestSourceIgnoredLinesCollector; + +/** + * Base class for language module tests. Automatically adds all common tests types for jplag languages. + */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public abstract class LanguageModuleTest { + private static final Path DEFAULT_TEST_CODE_PATH_BASE = Path.of("src", "test", "resources", "de", "jplag"); + + private final Logger LOG = Logger.getLogger(this.getClass().getName()); + + private final TestDataCollector collector; + private final Language language; + private final List languageTokens; + + /** + * Creates a new language module test + * @param language The language to test + * @param languageTokens All tokens, that can be reported by the module. The end file token can be omitted. + */ + public LanguageModuleTest(Language language, List languageTokens) { + this.language = language; + this.languageTokens = languageTokens; + this.collector = new TestDataCollector(this.getTestFileLocation()); + } + + /** + * Creates a new language module test + * @param language The language to test + * @param languageTokens All tokens, that can be reported by the module. The end file token can be omitted. + */ + public LanguageModuleTest(Language language, TokenType[] languageTokens) { + this(language, Arrays.asList(languageTokens)); + } + + /** + * Creates a new language module test + * @param language The language to test + * @param tokenEnum The enum containing the token types + */ + public & TokenType> LanguageModuleTest(Language language, Class tokenEnum) { + this(language, tokenEnum.getEnumConstants()); + } + + /** + * Test the configured source files for source line coverage + * @param data The source to check + * @throws ParsingException If the parser throws some error + * @throws IOException If any IO Exception occurs + */ + @ParameterizedTest + @MethodSource("sourceCoverageFiles") + @DisplayName("Test that every line leads to at least one token") + final void testSourceCoverage(TestData data) throws ParsingException, IOException { + List tokens = parseTokens(data); + + TestSourceIgnoredLinesCollector ignoredLines = new TestSourceIgnoredLinesCollector(data.getSourceLines()); + ignoredLines.ignoreEmptyLines(); + this.configureIgnoredLines(ignoredLines); + List relevantLines = new ArrayList<>(ignoredLines.getRelevantLines()); + + tokens.stream().map(Token::getLine).forEach(relevantLines::remove); + + assertTrue(relevantLines.isEmpty(), + "Test test source " + data.describeTestSource() + " contained uncovered lines:" + System.lineSeparator() + relevantLines); + } + + /** + * Returns all test sources, that need to be checked for source line coverage + * @return The test sources + */ + final List sourceCoverageFiles() { + return ignoreEmptyTestType(this.collector.getSourceCoverageData()); + } + + /** + * Checks the configured source files for token coverage + * @param data The source to check + * @throws ParsingException If the parser throws some error + * @throws IOException If any IO Exception occurs + */ + @ParameterizedTest + @MethodSource("tokenCoverageFiles") + @DisplayName("Test that every token occurs at least once") + final void testTokenCoverage(TestData data) throws ParsingException, IOException { + List actualTokens = extractTokenTypes(data); + List languageTokens = new ArrayList<>(this.languageTokens); + + languageTokens.removeAll(actualTokens); + + assertTrue(languageTokens.isEmpty(), "Some tokens were not found in " + data.describeTestSource() + System.lineSeparator() + languageTokens); + } + + /** + * Returns all test sources, that need to be checked for token coverage. + * @return The test sources + */ + final List tokenCoverageFiles() { + return ignoreEmptyTestType(this.collector.getTokenCoverageData()); + } + + /** + * Tests the configured test sources for contained tokens. The tokens neither have to occur exclusively nor in the given + * order. + * @param test The source to test + * @throws ParsingException If the parser throws some error + * @throws IOException If any IO Exception occurs + */ + @ParameterizedTest + @MethodSource("testTokensContainedData") + @DisplayName("Test that the specified tokens at least occur") + final void testTokensContained(TestDataCollector.TokenListTest test) throws ParsingException, IOException { + List actualTokens = extractTokenTypes(test.data()); + List expectedTokens = new ArrayList<>(test.tokens()); + + for (TokenType foundToken : actualTokens) { + expectedTokens.remove(foundToken); + } + + assertTrue(expectedTokens.isEmpty(), + "Some expected tokens were not found in " + test.data().describeTestSource() + System.lineSeparator() + expectedTokens); + } + + /** + * Returns all test sources, that need to be checked for contained tokens + * @return The test sources + */ + final List testTokensContainedData() { + return ignoreEmptyTestType(this.collector.getContainedTokenData()); + } + + /** + * Checks the given test sources for an exact token sequence + * @param test The source to check + * @throws ParsingException If the parser throws some error + * @throws IOException If any IO Exception occurs + */ + @ParameterizedTest + @MethodSource("testTokenSequenceData") + @DisplayName("Test if extracted token sequence matches") + final void testTokenSequence(TestDataCollector.TokenListTest test) throws ParsingException, IOException { + List actual = extractTokenTypes(test.data()); + List expected = new ArrayList<>(test.tokens()); + if (expected.get(expected.size() - 1) != SharedTokenType.FILE_END) { + expected.add(SharedTokenType.FILE_END); + } + assertTokensMatch(expected, actual, "Extracted token from " + test.data().describeTestSource() + " does not match expected sequence."); + assertIterableEquals(expected, actual); + } + + /** + * Convenience method for using assertLinesMatch with token lists. + */ + private void assertTokensMatch(List expected, List actual, String message) { + assertLinesMatch(expected.stream().map(Object::toString), actual.stream().map(Object::toString), message); + } + + /** + * Returns all test sources, that need to be checked for a matching token sequence + * @return The test sources + */ + final List testTokenSequenceData() { + return ignoreEmptyTestType(this.collector.getTokenSequenceTest()); + } + + /** + * Tests all configured test sources for a monotone order of tokens + * @param data The test source + * @throws ParsingException If the parser throws some error + * @throws IOException If any IO Exception occurs + */ + @ParameterizedTest + @MethodSource("getAllTestData") + @DisplayName("Test that the tokens map to ascending line numbers") + final void testMonotoneTokenOrder(TestData data) throws ParsingException, IOException { + List tokens = parseTokens(data); + + for (int i = 0; i < tokens.size() - 2; i++) { + Token first = tokens.get(i); + Token second = tokens.get(i + 1); + + if (first.getLine() > second.getLine()) { + fail(String.format("Invalid token order. Token %s has a higher line number (%s) than token %s (%s).", first.getType(), + first.getLine(), second.getType(), second.getLine())); + } + } + } + + /** + * Checks that all configured test sources end with a FileEnd token + * @param data The test source + * @throws ParsingException If the parser throws some error + * @throws IOException If any IO Exception occurs + */ + @ParameterizedTest + @MethodSource("getAllTestData") + @DisplayName("Test that the last token is the file end token") + final void testTokenSequencesEndsWithFileEnd(TestData data) throws ParsingException, IOException { + List tokens = parseTokens(data); + + assertEquals(SharedTokenType.FILE_END, tokens.get(tokens.size() - 1).getType(), + "Last token in " + data.describeTestSource() + " is not file end."); + } + + /** + * Returns all configured test sources + * @return The test sources + */ + final List getAllTestData() { + return ignoreEmptyTestType(this.collector.getAllTestData()); + } + + /** + * Collects the test sources + */ + @BeforeAll + final void collectTestData() { + collectTestData(this.collector); + } + + private List parseTokens(TestData source) throws ParsingException, IOException { + List tokens = source.parseTokens(this.language); + LOG.log(Level.INFO, TokenPrinter.printTokens(tokens)); + return tokens; + } + + private List extractTokenTypes(TestData source) throws ParsingException, IOException { + List tokens = parseTokens(source); + return tokens.stream().map(Token::getType).toList(); + } + + /** + * Ignores the test, if there is no data, by failing an assumption. + * @param data The list containing the test data + * @param The type of items + * @param The collection type + * @return The data + */ + private > C ignoreEmptyTestType(C data) { + Assumptions.assumeFalse(data.isEmpty(), "Ignoring empty test type."); + return data; + } + + /** + * Collects all tests, that should be executed. + * @param collector Use to collect the tests + */ + abstract protected void collectTestData(TestDataCollector collector); + + /** + * Configure which lines should not be checked for source coverage. + * @param collector Used to ignore lines + */ + abstract protected void configureIgnoredLines(TestSourceIgnoredLinesCollector collector); + + /** + * Returns the default directory structure by default. + * @return The test file location + */ + protected File getTestFileLocation() { + return new File(DEFAULT_TEST_CODE_PATH_BASE.toFile(), this.language.getIdentifier()); + } +} diff --git a/language-testutils/src/test/java/de/jplag/testutils/datacollector/FileTestData.java b/language-testutils/src/test/java/de/jplag/testutils/datacollector/FileTestData.java new file mode 100644 index 000000000..f2facf796 --- /dev/null +++ b/language-testutils/src/test/java/de/jplag/testutils/datacollector/FileTestData.java @@ -0,0 +1,58 @@ +package de.jplag.testutils.datacollector; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +import de.jplag.Language; +import de.jplag.ParsingException; +import de.jplag.Token; +import de.jplag.util.FileUtils; + +/** + * Provides test source from a file + */ +class FileTestData implements TestData { + private final File file; + + public FileTestData(File file) { + this.file = file; + } + + @Override + public List parseTokens(Language language) throws ParsingException { + return language.parse(Set.of(file)); + } + + @Override + public String[] getSourceLines() throws IOException { + return FileUtils.readFileContent(this.file).lines().toArray(String[]::new); + } + + @Override + public String describeTestSource() { + return "(File: " + this.file.getName() + ")"; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + FileTestData that = (FileTestData) o; + return Objects.equals(file, that.file); + } + + @Override + public int hashCode() { + return Objects.hash(file); + } + + @Override + public String toString() { + return this.file.getName(); + } +} diff --git a/language-testutils/src/test/java/de/jplag/testutils/datacollector/InlineTestData.java b/language-testutils/src/test/java/de/jplag/testutils/datacollector/InlineTestData.java new file mode 100644 index 000000000..d2ef73547 --- /dev/null +++ b/language-testutils/src/test/java/de/jplag/testutils/datacollector/InlineTestData.java @@ -0,0 +1,46 @@ +package de.jplag.testutils.datacollector; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +import de.jplag.Language; +import de.jplag.ParsingException; +import de.jplag.Token; +import de.jplag.util.FileUtils; + +/** + * Provides test source from a string + */ +class InlineTestData implements TestData { + private final String testData; + + public InlineTestData(String testData) { + this.testData = testData; + } + + @Override + public List parseTokens(Language language) throws ParsingException, IOException { + File file = File.createTempFile("testSource", language.suffixes()[0]); + FileUtils.write(file, this.testData); + List tokens = language.parse(Collections.singleton(file)); + file.delete(); + return tokens; + } + + @Override + public String[] getSourceLines() { + return this.testData.lines().toArray(String[]::new); + } + + @Override + public String describeTestSource() { + return "(inline source: " + this.testData + " )"; + } + + @Override + public String toString() { + return "inline: " + System.lineSeparator() + testData; + } +} diff --git a/language-testutils/src/test/java/de/jplag/testutils/datacollector/TestData.java b/language-testutils/src/test/java/de/jplag/testutils/datacollector/TestData.java new file mode 100644 index 000000000..b4e913d0e --- /dev/null +++ b/language-testutils/src/test/java/de/jplag/testutils/datacollector/TestData.java @@ -0,0 +1,35 @@ +package de.jplag.testutils.datacollector; + +import java.io.IOException; +import java.util.List; + +import de.jplag.Language; +import de.jplag.ParsingException; +import de.jplag.Token; + +/** + * Provides test code. Each instance represents a single source file. Serves as a way to encapsulate various locations + * for test code, such as files or java strings. + */ +public interface TestData { + /** + * Parses the tokens for this providers source. + * @param language The language to parse in + * @return The parsed tokens + * @throws ParsingException From language + * @throws IOException If any IO errors occur + */ + List parseTokens(Language language) throws ParsingException, IOException; + + /** + * @return A list of all source lines + * @throws IOException If any IO errors occur + */ + String[] getSourceLines() throws IOException; + + /** + * Describe the test source, to that it can be identified in error messages. + * @return The source description + */ + String describeTestSource(); +} diff --git a/language-testutils/src/test/java/de/jplag/testutils/datacollector/TestDataCollector.java b/language-testutils/src/test/java/de/jplag/testutils/datacollector/TestDataCollector.java new file mode 100644 index 000000000..c99a3741d --- /dev/null +++ b/language-testutils/src/test/java/de/jplag/testutils/datacollector/TestDataCollector.java @@ -0,0 +1,185 @@ +package de.jplag.testutils.datacollector; + +import java.io.File; +import java.util.*; +import java.util.stream.Collectors; + +import de.jplag.TokenType; + +/** + * Collects data for tests. Used by {@link de.jplag.testutils.LanguageModuleTest}s + */ +public class TestDataCollector { + private final List sourceCoverageData; + private final List tokenCoverageData; + private final List containedTokenData; + private final List tokenSequenceTest; + + private final List allTestData; + + private final File testFileLocation; + + /** + * Creates a new collector. Should only be called by {@link de.jplag.testutils.LanguageModuleTest} + * @param testFileLocation The location containing the test source files. + */ + public TestDataCollector(File testFileLocation) { + this.testFileLocation = testFileLocation; + + this.sourceCoverageData = new ArrayList<>(); + this.tokenCoverageData = new ArrayList<>(); + this.containedTokenData = new ArrayList<>(); + this.tokenSequenceTest = new ArrayList<>(); + + this.allTestData = new ArrayList<>(); + } + + /** + * Adds the given files to the test data. Returns a {@link TestDataContext}, that can be used to configure various tests + * on the given files. + * @param fileNames The names of the files to test + * @return The {@link TestDataContext} + */ + public TestDataContext testFile(String... fileNames) { + Set data = Arrays.stream(fileNames).map(it -> new File(this.testFileLocation, it)).map(FileTestData::new) + .collect(Collectors.toSet()); + return new TestDataContext(data); + } + + /** + * Adds all files matching a certain type. Returns a {@link TestDataContext}, that can be used to configure various + * tests on the given files. + * @param fileSuffix is the suffix of the files to be added. + * @return The {@link TestDataContext} + */ + public TestDataContext testAllOfType(String fileSuffix) { + Set data = Arrays.stream(testFileLocation.list()).filter(it -> it.endsWith(fileSuffix)) + .map(it -> new File(this.testFileLocation, it)).map(FileTestData::new).collect(Collectors.toSet()); + return new TestDataContext(data); + } + + /** + * Adds a list of source string to the test data. Returns a {@link TestDataContext}, that can be used to configure + * various tests on the given files. + * @param sources The list of sources + * @return The {@link TestDataContext} + */ + public TestDataContext inlineSource(String... sources) { + Set data = Arrays.stream(sources).map(InlineTestData::new).collect(Collectors.toSet()); + return new TestDataContext(data); + } + + /** + * @return The test data that should be checked for source coverage + */ + public List getSourceCoverageData() { + return Collections.unmodifiableList(sourceCoverageData); + } + + /** + * @return The test data that should be checked for token coverage + */ + public List getTokenCoverageData() { + return Collections.unmodifiableList(tokenCoverageData); + } + + /** + * @return The test data that should be checked for a contained set of tokens + */ + public List getContainedTokenData() { + return Collections.unmodifiableList(containedTokenData); + } + + /** + * @return The test data that should be checked for a specific sequence of tokens + */ + public List getTokenSequenceTest() { + return Collections.unmodifiableList(tokenSequenceTest); + } + + /** + * @return The list of all test data + */ + public List getAllTestData() { + return Collections.unmodifiableList(allTestData); + } + + /** + * Data for tests, that also require a list of tokens + * @param tokens The list of tokens + * @param data The test data + */ + public record TokenListTest(List tokens, TestData data) { + + @Override + public String toString() { + return data.toString(); // readable test name + } + } + + /** + * A builder used to configure tests for a set of data + */ + public class TestDataContext { + private final Set testData; + + private TestDataContext(Set testData) { + this.testData = testData; + allTestData.addAll(testData); + } + + /** + * Test the data set for source coverage + * @return self reference + */ + public TestDataContext testSourceCoverage() { + sourceCoverageData.addAll(testData); + return this; + } + + /** + * Test the data set for token coverage + * @return self reference + */ + public TestDataContext testTokenCoverage() { + tokenCoverageData.addAll(testData); + return this; + } + + /** + * Test the data set for source and token coverage. Behaves just like calling {@link this#testSourceCoverage()} and + * {@link this#testTokenCoverage()}. + * @return self reference + */ + public TestDataContext testCoverages() { + this.testSourceCoverage(); + this.testTokenCoverage(); + return this; + } + + /** + * Test the data set for contained tokens. The tokens neither have to occur exclusively nor in the given order. + * @param tokens The set of tokens to check for. + * @return self reference + */ + public TestDataContext testContainedTokens(TokenType... tokens) { + containedTokenData.addAll(listTestsFromArray(tokens)); + return this; + } + + /** + * Test the data set for a specific token sequence. The tokens have to be extracted in that exact order. The file end + * token can be omitted. + * @param tokens The sequence of tokens to check for + * @return self reference + */ + public TestDataContext testTokenSequence(TokenType... tokens) { + tokenSequenceTest.addAll(listTestsFromArray(tokens)); + return this; + } + + private List listTestsFromArray(TokenType... tokens) { + return this.testData.stream().map(it -> new TokenListTest(Arrays.asList(tokens), it)).toList(); + } + } +} diff --git a/language-testutils/src/test/java/de/jplag/testutils/datacollector/TestSourceIgnoredLinesCollector.java b/language-testutils/src/test/java/de/jplag/testutils/datacollector/TestSourceIgnoredLinesCollector.java new file mode 100644 index 000000000..2fff37ec1 --- /dev/null +++ b/language-testutils/src/test/java/de/jplag/testutils/datacollector/TestSourceIgnoredLinesCollector.java @@ -0,0 +1,72 @@ +package de.jplag.testutils.datacollector; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Predicate; + +public class TestSourceIgnoredLinesCollector { + private final String[] originalSource; + private final List relevantLines; + + public TestSourceIgnoredLinesCollector(String[] originalSource) { + this.originalSource = originalSource; + this.relevantLines = new ArrayList<>(); + + for (int i = 0; i < this.originalSource.length; i++) { + this.relevantLines.add(i + 1); + } + } + + public void ignoreEmptyLines() { + this.ignoreByCondition(String::isBlank); + } + + public void ignoreLinesByPrefix(String prefix) { + this.ignoreByCondition(line -> line.trim().startsWith(prefix)); + } + + public void ignoreLinesByContains(String content) { + this.ignoreByCondition(line -> line.contains(content)); + } + + public void ignoreMultipleLines(String startMarker, String endMarker) { + boolean inMultilineIgnore = false; + + for (int i = 0; i < this.relevantLines.size(); i++) { + String line = this.originalSource[i]; + if (!inMultilineIgnore) { + if (line.trim().startsWith(startMarker)) { + this.ignoreByIndex(i); + if (!line.trim().substring(startMarker.length() - 1).contains(endMarker)) { + inMultilineIgnore = true; + } + } + } else { + this.ignoreByIndex(i); + if (line.contains(endMarker)) { + inMultilineIgnore = false; + } + } + } + } + + public void ignoreMultipleLines(String startAndEnd) { + this.ignoreMultipleLines(startAndEnd, startAndEnd); + } + + public void ignoreByCondition(Predicate condition) { + for (int i = 0; i < this.originalSource.length; i++) { + if (condition.test(originalSource[i])) { + ignoreByIndex(i); + } + } + } + + public void ignoreByIndex(int index) { + this.relevantLines.remove((Object) (index + 1)); + } + + public List getRelevantLines() { + return this.relevantLines; + } +} diff --git a/languages/cpp/src/main/java/de/jplag/cpp/CPPTokenType.java b/languages/cpp/src/main/java/de/jplag/cpp/CPPTokenType.java index 312155fa1..e8143b98f 100644 --- a/languages/cpp/src/main/java/de/jplag/cpp/CPPTokenType.java +++ b/languages/cpp/src/main/java/de/jplag/cpp/CPPTokenType.java @@ -66,6 +66,7 @@ public enum CPPTokenType implements TokenType { private final String description; + @Override public String getDescription() { return this.description; } diff --git a/languages/cpp/src/main/java/de/jplag/cpp/experimental/GCCSourceAnalysis.java b/languages/cpp/src/main/java/de/jplag/cpp/experimental/GCCSourceAnalysis.java index 4b9371ff3..52b7bdfcd 100644 --- a/languages/cpp/src/main/java/de/jplag/cpp/experimental/GCCSourceAnalysis.java +++ b/languages/cpp/src/main/java/de/jplag/cpp/experimental/GCCSourceAnalysis.java @@ -24,6 +24,7 @@ public GCCSourceAnalysis() { this.logger = LoggerFactory.getLogger(this.getClass()); } + @Override public boolean isTokenIgnored(de.jplag.cpp.Token token, File file) { String fileName = file.getName(); if (linesToDelete.containsKey(fileName)) { @@ -33,6 +34,7 @@ public boolean isTokenIgnored(de.jplag.cpp.Token token, File file) { return false; } + @Override public void findUnusedVariableLines(Set files) throws InterruptedException { linesToDelete = new HashMap<>(); diff --git a/languages/cpp2/README.md b/languages/cpp2/README.md index 935b1b358..a8046b20f 100644 --- a/languages/cpp2/README.md +++ b/languages/cpp2/README.md @@ -27,6 +27,11 @@ More syntactic elements of C/C++ may turn out to be helpful to include in the fu To use the C++ frontend, add the `-l cpp2` flag in the CLI, or use a `JPlagOption` object with `new de.jplag.cpp2.CPPLanguage()` as `Language` in the Java API as described in the usage information in the [readme of the main project](https://github.com/jplag/JPlag#usage) and [in the wiki](https://github.com/jplag/JPlag/wiki/1.-How-to-Use-JPlag). +### Changes to the Grammar + +There is one change in our grammar compared to the original one. In the rule for "theOperator" 'DivAssign' was added as a case. +This is an error in the original version. +
#### Footnotes diff --git a/languages/cpp2/pom.xml b/languages/cpp2/pom.xml index 7339e6167..cfd8366cc 100644 --- a/languages/cpp2/pom.xml +++ b/languages/cpp2/pom.xml @@ -13,6 +13,11 @@ org.antlr antlr4-runtime + + de.jplag + language-antlr-utils + ${revision} + diff --git a/languages/cpp2/src/main/antlr4/de/jplag/cpp2/grammar/CPP14Parser.g4 b/languages/cpp2/src/main/antlr4/de/jplag/cpp2/grammar/CPP14Parser.g4 index d3a37438e..1be43aee5 100644 --- a/languages/cpp2/src/main/antlr4/de/jplag/cpp2/grammar/CPP14Parser.g4 +++ b/languages/cpp2/src/main/antlr4/de/jplag/cpp2/grammar/CPP14Parser.g4 @@ -790,6 +790,7 @@ theOperator: | GreaterEqual | PlusAssign | MinusAssign + | DivAssign // Different from the original grammar from the antlr repos. | StarAssign | ModAssign | XorAssign diff --git a/languages/cpp2/src/main/java/de/jplag/cpp2/CPPLanguage.java b/languages/cpp2/src/main/java/de/jplag/cpp2/CPPLanguage.java index d30647049..eef978912 100644 --- a/languages/cpp2/src/main/java/de/jplag/cpp2/CPPLanguage.java +++ b/languages/cpp2/src/main/java/de/jplag/cpp2/CPPLanguage.java @@ -1,26 +1,19 @@ package de.jplag.cpp2; -import java.io.File; -import java.util.List; -import java.util.Set; - import org.kohsuke.MetaInfServices; import de.jplag.Language; -import de.jplag.ParsingException; -import de.jplag.Token; +import de.jplag.antlr.AbstractAntlrLanguage; /** * The entry point for the ANTLR parser based C++ language module. */ @MetaInfServices(Language.class) -public class CPPLanguage implements Language { +public class CPPLanguage extends AbstractAntlrLanguage { private static final String IDENTIFIER = "cpp2"; - private final CPPParserAdapter parser; - public CPPLanguage() { - parser = new CPPParserAdapter(); + super(new CPPParserAdapter()); } @Override @@ -42,9 +35,4 @@ public String getIdentifier() { public int minimumTokenMatch() { return 12; } - - @Override - public List parse(Set files) throws ParsingException { - return this.parser.scan(files); - } } diff --git a/languages/cpp2/src/main/java/de/jplag/cpp2/CPPListener.java b/languages/cpp2/src/main/java/de/jplag/cpp2/CPPListener.java new file mode 100644 index 000000000..6b2a68c49 --- /dev/null +++ b/languages/cpp2/src/main/java/de/jplag/cpp2/CPPListener.java @@ -0,0 +1,99 @@ +package de.jplag.cpp2; + +import static de.jplag.cpp2.CPPTokenType.*; + +import de.jplag.antlr.AbstractAntlrListener; +import de.jplag.cpp2.grammar.CPP14Parser; +import de.jplag.cpp2.grammar.CPP14Parser.*; + +/** + * Extracts tokens from the ANTLR parse tree. Token extraction is built to be similar to the Java language module. In + * some cases, the grammar is ambiguous and requires surrounding context to extract the correct token. + *

+ * Those cases are covered by {@link SimpleTypeSpecifierContext} and {@link SimpleDeclarationContext} + */ +class CPPListener extends AbstractAntlrListener { + + CPPListener() { + visit(ClassSpecifierContext.class, rule -> rule.classHead().Union() != null).map(UNION_BEGIN, UNION_END); + visit(ClassSpecifierContext.class, rule -> rule.classHead().classKey() != null && rule.classHead().classKey().Class() != null) + .map(CLASS_BEGIN, CLASS_END); + visit(ClassSpecifierContext.class, rule -> rule.classHead().classKey() != null && rule.classHead().classKey().Struct() != null) + .map(STRUCT_BEGIN, STRUCT_END); + visit(EnumSpecifierContext.class).map(ENUM_BEGIN, ENUM_END); + + visit(FunctionDefinitionContext.class).map(FUNCTION_BEGIN, FUNCTION_END); + + visit(IterationStatementContext.class, rule -> rule.Do() != null).map(DO_BEGIN, DO_END); + visit(IterationStatementContext.class, rule -> rule.For() != null).map(FOR_BEGIN, FOR_END); + visit(IterationStatementContext.class, rule -> rule.While() != null && rule.Do() == null).map(WHILE_BEGIN, WHILE_END); + + visit(SelectionStatementContext.class, rule -> rule.Switch() != null).map(SWITCH_BEGIN, SWITCH_END); + visit(SelectionStatementContext.class, rule -> rule.If() != null).map(IF_BEGIN, IF_END); + visit(CPP14Parser.Else).map(ELSE); + + visit(LabeledStatementContext.class, rule -> rule.Case() != null).map(CASE); + visit(LabeledStatementContext.class, rule -> rule.Default() != null).map(DEFAULT); + + visit(TryBlockContext.class).map(TRY); + visit(HandlerContext.class).map(CATCH_BEGIN, CATCH_END); + + visit(JumpStatementContext.class, rule -> rule.Break() != null).map(BREAK); + visit(JumpStatementContext.class, rule -> rule.Continue() != null).map(CONTINUE); + visit(JumpStatementContext.class, rule -> rule.Goto() != null).map(GOTO); + visit(JumpStatementContext.class, rule -> rule.Return() != null).map(RETURN); + + visit(ThrowExpressionContext.class).map(THROW); + + visit(NewExpressionContext.class, rule -> rule.newInitializer() != null).map(NEWCLASS); + visit(NewExpressionContext.class, rule -> rule.newInitializer() == null).map(NEWARRAY); + + visit(TemplateDeclarationContext.class).map(GENERIC); + + visit(AssignmentOperatorContext.class).map(ASSIGN); + visit(BraceOrEqualInitializerContext.class, rule -> rule.Assign() != null).map(ASSIGN); + visit(UnaryExpressionContext.class, rule -> rule.PlusPlus() != null || rule.MinusMinus() != null).map(ASSIGN); + + visit(StaticAssertDeclarationContext.class).map(STATIC_ASSERT); + visit(EnumeratorDefinitionContext.class).map(VARDEF); + visit(BracedInitListContext.class).map(BRACED_INIT_BEGIN, BRACED_INIT_END); + + visit(SimpleTypeSpecifierContext.class, rule -> { + if (hasAncestor(rule, MemberdeclarationContext.class, FunctionDefinitionContext.class)) { + return true; + } + + if (hasAncestor(rule, SimpleDeclarationContext.class, TemplateArgumentContext.class, FunctionDefinitionContext.class)) { + SimpleDeclarationContext parent = getAncestor(rule, SimpleDeclarationContext.class); + NoPointerDeclaratorContext noPointerDecl = getDescendant(parent, NoPointerDeclaratorContext.class); + + return (!noPointerInFunctionCallContext(noPointerDecl)) && !hasAncestor(rule, NewTypeIdContext.class); + } + + return false; + }).map(VARDEF); + + visit(SimpleDeclarationContext.class, rule -> { + if (!hasAncestor(rule, FunctionBodyContext.class)) { + return false; + } + + NoPointerDeclaratorContext noPointerDecl = getDescendant(rule, NoPointerDeclaratorContext.class); + return noPointerInFunctionCallContext(noPointerDecl); + }).map(APPLY); + + visit(InitDeclaratorContext.class, rule -> rule.initializer() != null && rule.initializer().LeftParen() != null).map(APPLY); + visit(ParameterDeclarationContext.class).map(VARDEF); + visit(ConditionalExpressionContext.class, rule -> rule.Question() != null).map(QUESTIONMARK); + + visit(PostfixExpressionContext.class, rule -> rule.LeftParen() != null).map(APPLY); + visit(PostfixExpressionContext.class, rule -> rule.PlusPlus() != null || rule.MinusMinus() != null).map(ASSIGN); + } + + /** + * @return true of this context represents a function call + */ + private static boolean noPointerInFunctionCallContext(NoPointerDeclaratorContext context) { + return context != null && (context.parametersAndQualifiers() != null || context.LeftParen() != null); + } +} diff --git a/languages/cpp2/src/main/java/de/jplag/cpp2/CPPParserAdapter.java b/languages/cpp2/src/main/java/de/jplag/cpp2/CPPParserAdapter.java index c123dc29e..c876023ee 100644 --- a/languages/cpp2/src/main/java/de/jplag/cpp2/CPPParserAdapter.java +++ b/languages/cpp2/src/main/java/de/jplag/cpp2/CPPParserAdapter.java @@ -1,66 +1,39 @@ package de.jplag.cpp2; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - -import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CommonTokenStream; -import org.antlr.v4.runtime.tree.ParseTreeWalker; +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.ParserRuleContext; import de.jplag.AbstractParser; -import de.jplag.ParsingException; -import de.jplag.Token; -import de.jplag.TokenType; +import de.jplag.antlr.AbstractAntlrListener; +import de.jplag.antlr.AbstractAntlrParserAdapter; import de.jplag.cpp2.grammar.CPP14Lexer; import de.jplag.cpp2.grammar.CPP14Parser; /** * The adapter between {@link AbstractParser} and the ANTLR based parser of this language module. */ -public class CPPParserAdapter extends AbstractParser { - private File currentFile; - - private List tokens; +public class CPPParserAdapter extends AbstractAntlrParserAdapter { + private static final CPPListener listener = new CPPListener(); - /** - * {@return a list of tokens from a set of source files} - * @param files the source files - * @throws ParsingException if parsing fails. - */ - public List scan(Set files) throws ParsingException { - tokens = new ArrayList<>(); - for (File file : files) { - this.currentFile = file; - logger.trace("Parsing file {}", currentFile); - try { - CPP14Lexer lexer = new CPP14Lexer(CharStreams.fromStream(Files.newInputStream(file.toPath()))); - // create a buffer of tokens pulled from the lexer - CommonTokenStream tokenStream = new CommonTokenStream(lexer); - CPP14Parser parser = new CPP14Parser(tokenStream); - CPP14Parser.TranslationUnitContext translationUnit = parser.translationUnit(); + @Override + protected Lexer createLexer(CharStream input) { + return new CPP14Lexer(input); + } - ParseTreeWalker.DEFAULT.walk(new CPPTokenListener(this), translationUnit); - } catch (IOException e) { - throw new ParsingException(file, e); - } - tokens.add(Token.fileEnd(currentFile)); - } - return tokens; + @Override + protected CPP14Parser createParser(CommonTokenStream tokenStream) { + return new CPP14Parser(tokenStream); } - /** - * Add a token with the given type at the given position (column and line) with the given length. - * @param type the type of the token. - * @param column the column where the token starts. - * @param line the line where the token starts. - * @param length the length of the token. - */ - public void addToken(TokenType type, int column, int line, int length) { - tokens.add(new Token(type, currentFile, line, column, length)); + @Override + protected ParserRuleContext getEntryContext(CPP14Parser parser) { + return parser.translationUnit(); } + @Override + protected AbstractAntlrListener getListener() { + return listener; + } } diff --git a/languages/cpp2/src/main/java/de/jplag/cpp2/CPPTokenListener.java b/languages/cpp2/src/main/java/de/jplag/cpp2/CPPTokenListener.java deleted file mode 100644 index 70af74c69..000000000 --- a/languages/cpp2/src/main/java/de/jplag/cpp2/CPPTokenListener.java +++ /dev/null @@ -1,488 +0,0 @@ -package de.jplag.cpp2; - -import static de.jplag.cpp2.CPPTokenType.APPLY; -import static de.jplag.cpp2.CPPTokenType.ASSIGN; -import static de.jplag.cpp2.CPPTokenType.BRACED_INIT_BEGIN; -import static de.jplag.cpp2.CPPTokenType.BRACED_INIT_END; -import static de.jplag.cpp2.CPPTokenType.BREAK; -import static de.jplag.cpp2.CPPTokenType.CASE; -import static de.jplag.cpp2.CPPTokenType.CATCH_BEGIN; -import static de.jplag.cpp2.CPPTokenType.CATCH_END; -import static de.jplag.cpp2.CPPTokenType.CLASS_BEGIN; -import static de.jplag.cpp2.CPPTokenType.CLASS_END; -import static de.jplag.cpp2.CPPTokenType.CONTINUE; -import static de.jplag.cpp2.CPPTokenType.DEFAULT; -import static de.jplag.cpp2.CPPTokenType.DO_BEGIN; -import static de.jplag.cpp2.CPPTokenType.DO_END; -import static de.jplag.cpp2.CPPTokenType.ELSE; -import static de.jplag.cpp2.CPPTokenType.ENUM_BEGIN; -import static de.jplag.cpp2.CPPTokenType.ENUM_END; -import static de.jplag.cpp2.CPPTokenType.FOR_BEGIN; -import static de.jplag.cpp2.CPPTokenType.FOR_END; -import static de.jplag.cpp2.CPPTokenType.FUNCTION_BEGIN; -import static de.jplag.cpp2.CPPTokenType.FUNCTION_END; -import static de.jplag.cpp2.CPPTokenType.GENERIC; -import static de.jplag.cpp2.CPPTokenType.GOTO; -import static de.jplag.cpp2.CPPTokenType.IF_BEGIN; -import static de.jplag.cpp2.CPPTokenType.IF_END; -import static de.jplag.cpp2.CPPTokenType.NEWARRAY; -import static de.jplag.cpp2.CPPTokenType.NEWCLASS; -import static de.jplag.cpp2.CPPTokenType.QUESTIONMARK; -import static de.jplag.cpp2.CPPTokenType.RETURN; -import static de.jplag.cpp2.CPPTokenType.STATIC_ASSERT; -import static de.jplag.cpp2.CPPTokenType.STRUCT_BEGIN; -import static de.jplag.cpp2.CPPTokenType.STRUCT_END; -import static de.jplag.cpp2.CPPTokenType.SWITCH_BEGIN; -import static de.jplag.cpp2.CPPTokenType.SWITCH_END; -import static de.jplag.cpp2.CPPTokenType.THROW; -import static de.jplag.cpp2.CPPTokenType.TRY; -import static de.jplag.cpp2.CPPTokenType.UNION_BEGIN; -import static de.jplag.cpp2.CPPTokenType.UNION_END; -import static de.jplag.cpp2.CPPTokenType.VARDEF; -import static de.jplag.cpp2.CPPTokenType.WHILE_BEGIN; -import static de.jplag.cpp2.CPPTokenType.WHILE_END; -import static de.jplag.cpp2.grammar.CPP14Parser.RULE_selectionStatement; - -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.function.Function; -import java.util.function.Predicate; - -import org.antlr.v4.runtime.ParserRuleContext; -import org.antlr.v4.runtime.Token; -import org.antlr.v4.runtime.tree.ParseTree; - -import de.jplag.TokenType; -import de.jplag.cpp2.grammar.CPP14Parser.AssignmentOperatorContext; -import de.jplag.cpp2.grammar.CPP14Parser.BraceOrEqualInitializerContext; -import de.jplag.cpp2.grammar.CPP14Parser.BracedInitListContext; -import de.jplag.cpp2.grammar.CPP14Parser.ClassSpecifierContext; -import de.jplag.cpp2.grammar.CPP14Parser.ConditionalExpressionContext; -import de.jplag.cpp2.grammar.CPP14Parser.EnumSpecifierContext; -import de.jplag.cpp2.grammar.CPP14Parser.EnumeratorDefinitionContext; -import de.jplag.cpp2.grammar.CPP14Parser.FunctionBodyContext; -import de.jplag.cpp2.grammar.CPP14Parser.FunctionDefinitionContext; -import de.jplag.cpp2.grammar.CPP14Parser.HandlerContext; -import de.jplag.cpp2.grammar.CPP14Parser.IterationStatementContext; -import de.jplag.cpp2.grammar.CPP14Parser.JumpStatementContext; -import de.jplag.cpp2.grammar.CPP14Parser.LabeledStatementContext; -import de.jplag.cpp2.grammar.CPP14Parser.MemberdeclarationContext; -import de.jplag.cpp2.grammar.CPP14Parser.NewExpressionContext; -import de.jplag.cpp2.grammar.CPP14Parser.NewTypeIdContext; -import de.jplag.cpp2.grammar.CPP14Parser.NoPointerDeclaratorContext; -import de.jplag.cpp2.grammar.CPP14Parser.ParameterDeclarationContext; -import de.jplag.cpp2.grammar.CPP14Parser.PostfixExpressionContext; -import de.jplag.cpp2.grammar.CPP14Parser.SelectionStatementContext; -import de.jplag.cpp2.grammar.CPP14Parser.SimpleDeclarationContext; -import de.jplag.cpp2.grammar.CPP14Parser.SimpleTypeSpecifierContext; -import de.jplag.cpp2.grammar.CPP14Parser.StatementContext; -import de.jplag.cpp2.grammar.CPP14Parser.StaticAssertDeclarationContext; -import de.jplag.cpp2.grammar.CPP14Parser.TemplateArgumentContext; -import de.jplag.cpp2.grammar.CPP14Parser.TemplateDeclarationContext; -import de.jplag.cpp2.grammar.CPP14Parser.ThrowExpressionContext; -import de.jplag.cpp2.grammar.CPP14Parser.TryBlockContext; -import de.jplag.cpp2.grammar.CPP14Parser.UnaryExpressionContext; -import de.jplag.cpp2.grammar.CPP14ParserBaseListener; - -/** - * Extracts tokens from the ANTLR parse tree. Token extraction is built to be similar to the Java language module. In - * some cases, the grammar is ambiguous and requires surrounding context to extract the correct token. Those cases are - * covered by {@link #enterSimpleTypeSpecifier(SimpleTypeSpecifierContext)} and - * {@link #enterSimpleDeclaration(SimpleDeclarationContext)}. - */ -public class CPPTokenListener extends CPP14ParserBaseListener { - - private final CPPParserAdapter parser; - private final Deque trackedState = new ArrayDeque<>(); - private Token lastElseToken; - - /** - * Constructs a new token listener that will extract tokens to the given {@link CPPParserAdapter}. - * @param parser the adapter to pass extracted tokens to. - */ - public CPPTokenListener(CPPParserAdapter parser) { - this.parser = parser; - } - - private static final List> CLASS_SPECIFIER_TOKENS = List.of( - Extraction.of(context -> context.classHead().Union(), UNION_BEGIN, UNION_END), - Extraction.of(context -> context.classHead().classKey().Class(), CLASS_BEGIN, CLASS_END), - Extraction.of(context -> context.classHead().classKey().Struct(), STRUCT_BEGIN, STRUCT_END)); - - @Override - public void enterClassSpecifier(ClassSpecifierContext context) { - extractFirstNonNullStartToken(context, context.getStart(), CLASS_SPECIFIER_TOKENS); - } - - @Override - public void exitClassSpecifier(ClassSpecifierContext context) { - extractFirstNonNullEndToken(context, context.getStop(), CLASS_SPECIFIER_TOKENS); - } - - @Override - public void enterEnumSpecifier(EnumSpecifierContext context) { - addEnter(ENUM_BEGIN, context.getStart()); - } - - @Override - public void exitEnumSpecifier(EnumSpecifierContext context) { - addExit(ENUM_END, context.getStop()); - } - - @Override - public void enterFunctionDefinition(FunctionDefinitionContext context) { - addEnter(FUNCTION_BEGIN, context.getStart()); - } - - @Override - public void exitFunctionDefinition(FunctionDefinitionContext context) { - addExit(FUNCTION_END, context.getStop()); - } - - private static final List> ITERATION_STATEMENT_TOKENS = List.of( - Extraction.of(IterationStatementContext::Do, DO_BEGIN, DO_END), Extraction.of(IterationStatementContext::For, FOR_BEGIN, FOR_END), - Extraction.of(IterationStatementContext::While, WHILE_BEGIN, WHILE_END)); - - @Override - public void enterIterationStatement(IterationStatementContext context) { - extractFirstNonNullStartToken(context, context.getStart(), ITERATION_STATEMENT_TOKENS); - } - - @Override - public void exitIterationStatement(IterationStatementContext context) { - extractFirstNonNullEndToken(context, context.getStop(), ITERATION_STATEMENT_TOKENS); - } - - /** - * Extract tokens for {@code if} and {@code switch}. To extract {@link CPPTokenType#ELSE} after the tokens inside the if - * block but before the tokens in the else block, {@link #trackedState} works as a stack of the current state. - * {@link CPPTokenType#IF_END} is only extracted after the whole tree element (including else), to be consistent with - * the Java language module. - * @param context the selection statement. - */ - @Override - public void enterSelectionStatement(SelectionStatementContext context) { - if (context.Switch() != null) { - addEnter(SWITCH_BEGIN, context.getStart()); - this.trackedState.add(CPPTokenType.SWITCH_END); - } else if (context.If() != null) { - addEnter(IF_BEGIN, context.getStart()); - if (context.Else() != null) { - this.trackedState.add(ELSE); - this.lastElseToken = context.Else().getSymbol(); - } - this.trackedState.add(CPPTokenType.IF_END); - } - } - - @Override - public void enterStatement(StatementContext context) { - if (context.getParent().getRuleIndex() == RULE_selectionStatement && this.trackedState.peekLast() == CPPTokenType.ELSE) { - addEnter(trackedState.removeLast(), this.lastElseToken); - } - } - - @Override - public void exitStatement(StatementContext context) { - if (context.getParent().getRuleIndex() == RULE_selectionStatement && this.trackedState.peekLast() == CPPTokenType.IF_END) { - // drop if end token from state, but do not add it yet (see exitSelectionStatement) - trackedState.removeLast(); - } - } - - @Override - public void exitSelectionStatement(SelectionStatementContext context) { - if (context.Switch() != null) { - addEnter(SWITCH_END, context.getStop()); - } else if (context.If() != null) { - addEnter(IF_END, context.getStop()); - } - } - - private static final List> LABELED_STATEMENT_TOKES = List - .of(Extraction.of(LabeledStatementContext::Case, CASE), Extraction.of(LabeledStatementContext::Default, DEFAULT)); - - @Override - public void enterLabeledStatement(LabeledStatementContext context) { - extractFirstNonNullStartToken(context, context.start, LABELED_STATEMENT_TOKES); - } - - @Override - public void enterTryBlock(TryBlockContext context) { - addEnter(TRY, context.getStart()); - } - - @Override - public void enterHandler(HandlerContext context) { - addEnter(CATCH_BEGIN, context.getStart()); - } - - @Override - public void exitHandler(HandlerContext context) { - addEnter(CATCH_END, context.getStop()); - } - - private static final List> JUMP_STATEMENT_TOKENS = List.of(Extraction.of(JumpStatementContext::Break, BREAK), - Extraction.of(JumpStatementContext::Continue, CONTINUE), Extraction.of(JumpStatementContext::Goto, GOTO), - Extraction.of(JumpStatementContext::Return, RETURN)); - - @Override - public void enterJumpStatement(JumpStatementContext context) { - extractFirstNonNullStartToken(context, context.getStart(), JUMP_STATEMENT_TOKENS); - } - - @Override - public void enterThrowExpression(ThrowExpressionContext context) { - addEnter(THROW, context.getStart()); - } - - private static final List> NEW_EXPRESSION_TOKENS = List - .of(Extraction.of(NewExpressionContext::newInitializer, NEWCLASS), Extraction.fallback(NEWARRAY)); - - @Override - public void enterNewExpression(NewExpressionContext context) { - extractFirstNonNullStartToken(context, context.getStart(), NEW_EXPRESSION_TOKENS); - } - - @Override - public void enterTemplateDeclaration(TemplateDeclarationContext context) { - addEnter(GENERIC, context.getStart()); - } - - @Override - public void enterAssignmentOperator(AssignmentOperatorContext context) { - // does not cover ++, --, this is done via UnaryExpressionContext and PostfixExpressionContext - // does not cover all =, this is done via BraceOrEqualInitializerContext - addEnter(ASSIGN, context.getStart()); - } - - @Override - public void enterBraceOrEqualInitializer(BraceOrEqualInitializerContext context) { - if (context.Assign() != null) { - addEnter(ASSIGN, context.getStart()); - } - } - - @Override - public void enterUnaryExpression(UnaryExpressionContext context) { - if (context.PlusPlus() != null || context.MinusMinus() != null) { - addEnter(ASSIGN, context.getStart()); - } - } - - @Override - public void enterStaticAssertDeclaration(StaticAssertDeclarationContext context) { - addEnter(STATIC_ASSERT, context.getStart()); - } - - @Override - public void enterEnumeratorDefinition(EnumeratorDefinitionContext context) { - addEnter(VARDEF, context.getStart()); - } - - @Override - public void enterBracedInitList(BracedInitListContext context) { - addEnter(BRACED_INIT_BEGIN, context.getStart()); - } - - @Override - public void exitBracedInitList(BracedInitListContext context) { - addExit(BRACED_INIT_END, context.getStop()); - } - - /** - * Covers {@link CPPTokenType#VARDEF} extraction. The grammar is ambiguous here, so inspecting the surrounding tree - * elements is required to not extract {@link CPPTokenType#VARDEF} in places of type declarations, function calls and - * template arguments. - */ - @Override - public void enterSimpleTypeSpecifier(SimpleTypeSpecifierContext context) { - if (hasAncestor(context, MemberdeclarationContext.class, FunctionDefinitionContext.class)) { - addEnter(VARDEF, context.getStart()); - } else if (hasAncestor(context, SimpleDeclarationContext.class, TemplateArgumentContext.class, FunctionDefinitionContext.class)) { - // part of a SimpleDeclaration without being part of - // - a TemplateArgument (vector v) - // - a FunctionDefinition (return type, parameters) (parameters are extracted in enterParameterDeclaration as VARDEF) - // first. - SimpleDeclarationContext parent = getAncestor(context, SimpleDeclarationContext.class); - assert parent != null; // already checked by hasAncestor - NoPointerDeclaratorContext noPointerDecl = getDescendant(parent, NoPointerDeclaratorContext.class); - if ((!noPointerInFunctionCallContext(noPointerDecl)) && !hasAncestor(context, NewTypeIdContext.class)) { - // 'new ' does not declare a new variable - addEnter(VARDEF, context.getStart()); - } - } - } - - @Override - public void enterSimpleDeclaration(SimpleDeclarationContext context) { - if (!hasAncestor(context, FunctionBodyContext.class)) { - // not in a context where a function call can appear, assume it's a function definition - return; - } - NoPointerDeclaratorContext noPointerDecl = getDescendant(context, NoPointerDeclaratorContext.class); - if (noPointerInFunctionCallContext(noPointerDecl)) { - // method calls like A::b(), b() - addEnter(APPLY, noPointerDecl.getStart()); - } - } - - /** - * {@return true of this context represents a function call} - */ - private static boolean noPointerInFunctionCallContext(NoPointerDeclaratorContext context) { - return context != null && (context.parametersAndQualifiers() != null || context.LeftParen() != null); - } - - @Override - public void enterParameterDeclaration(ParameterDeclarationContext context) { - addEnter(VARDEF, context.getStart()); - } - - @Override - public void enterConditionalExpression(ConditionalExpressionContext context) { - if (context.Question() != null) { - addEnter(QUESTIONMARK, context.getStart()); - } - } - - private static final List> POSTFIX_EXPRESSION_TOKENS = List.of( - Extraction.of(PostfixExpressionContext::LeftParen, APPLY), Extraction.of(PostfixExpressionContext::PlusPlus, ASSIGN), - Extraction.of(PostfixExpressionContext::MinusMinus, ASSIGN)); - - @Override - public void enterPostfixExpression(PostfixExpressionContext context) { - // additional function calls are handled in SimpleDeclarationContext - extractFirstNonNullStartToken(context, context.getStart(), POSTFIX_EXPRESSION_TOKENS); - } - - /** - * Searches a subtree for a descendant of a specific type. Search is done breath-first. - * @param context the context to search the subtree from. - * @param descendant the class representing the type to search for. - * @param the type to search for. - * @return the first appearance of an element of the given type in the subtree, or null if no such element exists. - */ - private T getDescendant(ParserRuleContext context, Class descendant) { - // simple iterative bfs - ArrayDeque queue = new ArrayDeque<>(); - queue.add(context); - while (!queue.isEmpty()) { - ParserRuleContext next = queue.removeFirst(); - for (ParseTree tree : next.children) { - if (tree.getClass() == descendant) { - return descendant.cast(tree); - } - if (tree instanceof ParserRuleContext parserRuleContext) { - queue.addLast(parserRuleContext); - } - } - } - return null; - } - - /** - * Searches the ancestors of an element for an element of the specific type. - * @param context the current element to start the search from. - * @param ancestor the class representing the type to search for. - * @param stops the types of elements to stop the upward search at. - * @param the type of the element to search for. - * @return an ancestor of the specified type, or null if not found. - */ - @SafeVarargs - private T getAncestor(ParserRuleContext context, Class ancestor, Class... stops) { - ParserRuleContext currentcontext = context; - Set> forbidden = Set.of(stops); - do { - ParserRuleContext next = currentcontext.getParent(); - if (next == null) { - return null; - } - if (next.getClass() == ancestor) { - return ancestor.cast(next); - } - if (forbidden.contains(next.getClass())) { - return null; - } - currentcontext = next; - } while (true); - } - - /** - * {@return true if an ancestor of the specified type exists} - * @param context the current element to start the search from. - * @param parent the class representing the type to search for. - * @param stops the types of elements to stop the upward search at. - * @see #getAncestor(ParserRuleContext, Class, Class[]) - */ - @SafeVarargs - private boolean hasAncestor(ParserRuleContext context, Class parent, Class... stops) { - return getAncestor(context, parent, stops) != null; - } - - // extraction utilities - - private void addEnter(TokenType type, Token token) { - addTokenWithLength(type, token, token.getText().length()); - } - - private void addExit(TokenType type, Token token) { - addTokenWithLength(type, token, 1); - } - - private void addTokenWithLength(TokenType type, Token token, int length) { - int column = token.getCharPositionInLine() + 1; - this.parser.addToken(type, column, token.getLine(), length); - } - - /** - * Describes an extraction rule. If the extraction test returns true, one of the given token types is extracted. - * @param extractionTest the test whether the rule matches. - * @param startToken the token extracted for this rule in {@code enter*} contexts - * @param endToken the token extracted for this rule in {@code exit*} contexts - * @param the input type - */ - private record Extraction(Predicate extractionTest, TokenType startToken, TokenType endToken) { - - /** - * Creates an Extraction rule that matches if the value returned by the given function is non-null. - */ - static Extraction of(Function contextToAnything, TokenType startToken) { - return of(contextToAnything, startToken, null); - } - - static Extraction of(Function contextToAnything, TokenType startToken, TokenType endToken) { - // go from (T -> ?) to (T -> boolean) - Predicate isNonNull = t -> contextToAnything.andThen(Objects::nonNull).apply(t); - return new Extraction<>(isNonNull, startToken, endToken); - } - - static Extraction fallback(TokenType toExtract) { - return new Extraction<>(t -> true, toExtract, null); - } - } - - private void extractFirstNonNullEndToken(T context, Token token, List> extractions) { - extractFirstNonNull(context, token, extractions, false); - } - - private void extractFirstNonNullStartToken(T context, Token token, List> extractions) { - extractFirstNonNull(context, token, extractions, true); - } - - private void extractFirstNonNull(T context, Token token, List> extractions, boolean start) { - for (Extraction extraction : extractions) { - if (extraction.extractionTest().test(context)) { - if (start) { - addEnter(extraction.startToken(), token); - } else { - addExit(extraction.endToken(), token); - } - return; - } - } - } -} diff --git a/languages/cpp2/src/main/java/de/jplag/cpp2/CPPTokenType.java b/languages/cpp2/src/main/java/de/jplag/cpp2/CPPTokenType.java index 018717717..0a072d0ac 100644 --- a/languages/cpp2/src/main/java/de/jplag/cpp2/CPPTokenType.java +++ b/languages/cpp2/src/main/java/de/jplag/cpp2/CPPTokenType.java @@ -45,7 +45,6 @@ public enum CPPTokenType implements TokenType { STATIC_ASSERT("STATIC_ASSERT"), VARDEF("VARDEF"), QUESTIONMARK("COND"), - ATTRIBUTE("ATTRIBUTE"), DEFAULT("DEFAULT"), APPLY("APPLY"); diff --git a/languages/cpp2/src/test/java/de/jplag/cpp2/CppLanguageTest.java b/languages/cpp2/src/test/java/de/jplag/cpp2/CppLanguageTest.java new file mode 100644 index 000000000..52d4342d9 --- /dev/null +++ b/languages/cpp2/src/test/java/de/jplag/cpp2/CppLanguageTest.java @@ -0,0 +1,105 @@ +package de.jplag.cpp2; + +import java.util.Arrays; + +import de.jplag.testutils.LanguageModuleTest; +import de.jplag.testutils.datacollector.TestDataCollector; +import de.jplag.testutils.datacollector.TestSourceIgnoredLinesCollector; + +/** + * These tests attempt to cover the cpp module in multiple ways. These are the tests currently contained: + *

+ * - As the ANTLR grammar requires some workarounds to have the token extraction similar to the Java language module, + * there are tests to cover the extraction of such tokens. - Ensures that all tokens are extracted at some point and + * source files are suitably covered by testing a huge file (bc6h_enc.h) + */ +public class CppLanguageTest extends LanguageModuleTest { + private static final String[] assignSnippets = {"i = 10", "i += 10", "i -= 10", "i += 10", "i /= 10", "i %= 10", "i >>= 10", "i <<= 10", + "i &= 10", "i ^= 10", "i |= 10", "i++", "i--", "++i", "--i"}; + + private static final String[] functionCallSnippets = {"this->myMethod(v)", "MyClass::myMethod(v)", "myMethod(v)", "m.myMethod(v)", "myMethod(1)", + "myMethod(\"a\")"}; + + private static final String intMethodCallFormatter = """ + void f(int i) { + %s; + } + """; + + private static final String stringMethodCallFormatter = """ + void a(string v) { + %s; + } + """; + + public CppLanguageTest() { + super(new CPPLanguage(), CPPTokenType.class); + } + + @Override + protected void collectTestData(TestDataCollector collector) { + collector.inlineSource(formattedCode(intMethodCallFormatter, assignSnippets)).testContainedTokens(CPPTokenType.ASSIGN).testSourceCoverage(); + + collector.testFile("FunctionCall.cpp").testTokenSequence(CPPTokenType.FUNCTION_BEGIN, CPPTokenType.APPLY, CPPTokenType.APPLY, + CPPTokenType.APPLY, CPPTokenType.APPLY, CPPTokenType.FUNCTION_END).testSourceCoverage(); + + collector.testFile("Loop.cpp") + .testTokenSequence(CPPTokenType.FUNCTION_BEGIN, CPPTokenType.DO_BEGIN, CPPTokenType.GOTO, CPPTokenType.DO_END, + CPPTokenType.WHILE_BEGIN, CPPTokenType.BREAK, CPPTokenType.WHILE_END, CPPTokenType.FOR_BEGIN, CPPTokenType.CONTINUE, + CPPTokenType.FOR_END, CPPTokenType.RETURN, CPPTokenType.FUNCTION_END) + .testSourceCoverage(); + + collector.inlineSource(formattedCode(stringMethodCallFormatter, functionCallSnippets)) + .testTokenSequence(CPPTokenType.FUNCTION_BEGIN, CPPTokenType.VARDEF, CPPTokenType.APPLY, CPPTokenType.FUNCTION_END) + .testSourceCoverage(); + + collector.testFile("IfElse.cpp").testTokenSequence(CPPTokenType.FUNCTION_BEGIN, CPPTokenType.VARDEF, CPPTokenType.VARDEF, CPPTokenType.VARDEF, + CPPTokenType.VARDEF, CPPTokenType.IF_BEGIN, CPPTokenType.ASSIGN, CPPTokenType.ELSE, CPPTokenType.IF_BEGIN, CPPTokenType.ASSIGN, + CPPTokenType.ASSIGN, CPPTokenType.ELSE, CPPTokenType.ASSIGN, CPPTokenType.IF_END, CPPTokenType.IF_END, CPPTokenType.FUNCTION_END) + .testSourceCoverage(); + + collector.inlineSource("double* b = new double[10];").testTokenSequence(CPPTokenType.VARDEF, CPPTokenType.ASSIGN, CPPTokenType.NEWARRAY); + + collector.inlineSource("int x = square(2);").testTokenSequence(CPPTokenType.VARDEF, CPPTokenType.ASSIGN, CPPTokenType.APPLY); + + collector.testFile("CallOutsideMethodInClass.cpp").testTokenSequence(CPPTokenType.CLASS_BEGIN, CPPTokenType.VARDEF, CPPTokenType.ASSIGN, + CPPTokenType.APPLY, CPPTokenType.CLASS_END); + + collector.testFile("Union.cpp") + .testTokenSequence(CPPTokenType.UNION_BEGIN, CPPTokenType.VARDEF, CPPTokenType.VARDEF, CPPTokenType.VARDEF, CPPTokenType.UNION_END) + .testSourceCoverage(); + + collector.testFile("IntArray.cpp").testTokenSequence(CPPTokenType.VARDEF, CPPTokenType.ASSIGN, CPPTokenType.BRACED_INIT_BEGIN, + CPPTokenType.BRACED_INIT_END, CPPTokenType.VARDEF, CPPTokenType.BRACED_INIT_BEGIN, CPPTokenType.BRACED_INIT_END); + + collector.testFile("bc6h_enc.h").testCoverages(); + + collector.inlineSource(""" + void test() { + if(true) { + if(false) { + } else { + } + } else { + } + } + """); + } + + @Override + protected void configureIgnoredLines(TestSourceIgnoredLinesCollector collector) { + collector.ignoreByCondition(line -> line.matches(" *[a-zA-Z]+: *")); + collector.ignoreByCondition(line -> line.matches(" *\\{*")); + collector.ignoreLinesByPrefix("}"); + collector.ignoreLinesByPrefix("//"); + collector.ignoreLinesByPrefix("#"); + collector.ignoreLinesByPrefix("namespace"); + collector.ignoreLinesByPrefix("using"); + collector.ignoreMultipleLines("/*", "*/"); + collector.ignoreLinesByContains("else"); + } + + private String[] formattedCode(String formatter, String... snippets) { + return Arrays.stream(snippets).map(formatter::formatted).toArray(String[]::new); + } +} diff --git a/languages/cpp2/src/test/java/de/jplag/cpp2/TokenExtractionTest.java b/languages/cpp2/src/test/java/de/jplag/cpp2/TokenExtractionTest.java deleted file mode 100644 index 4ab7724dc..000000000 --- a/languages/cpp2/src/test/java/de/jplag/cpp2/TokenExtractionTest.java +++ /dev/null @@ -1,210 +0,0 @@ -package de.jplag.cpp2; - -import static org.junit.jupiter.api.Assertions.*; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.List; -import java.util.Set; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; -import org.opentest4j.TestAbortedException; - -import de.jplag.ParsingException; -import de.jplag.SharedTokenType; -import de.jplag.Token; -import de.jplag.TokenPrinter; -import de.jplag.TokenType; - -/** - * Tests asserting the extraction of nontrivial tokens. As the ANTLR grammar requires some workarounds to have the token - * extraction similar to the Java language module, these tests covers the extraction of such tokens. - */ -class TokenExtractionTest { - - @ParameterizedTest - @ValueSource(strings = {"i = 10", "i += 10", "i -= 10", "i += 10", "i /= 10", "i %= 10", "i >>= 10", "i <<= 10", "i &= 10", "i ^= 10", "i |= 10", - "i++", "i--", "++i", "--i",}) - void testAssign(String expr, @TempDir Path path) { - String function = """ - void f(int i) { - %s; - } - """.formatted(expr); - List all = extractFromString(path, function).tokens(); - List assignTokens = all.stream().filter(token -> token.getType() == CPPTokenType.ASSIGN).toList(); - assertEquals(1, assignTokens.size()); - } - - @Test - void testFunctionCall(@TempDir Path path) { - TokenResult result = extractFromString(path, """ - void f() { - b->funCall(); - C::funCall(); - funCall(); - a.funCall(); - } - """); - System.out.println(TokenPrinter.printTokens(result.tokens(), result.file())); - assertTokenTypes(result.tokens(), CPPTokenType.FUNCTION_BEGIN, CPPTokenType.APPLY, CPPTokenType.APPLY, CPPTokenType.APPLY, CPPTokenType.APPLY, - CPPTokenType.FUNCTION_END); - } - - @Test - void testLoop(@TempDir Path path) { - TokenResult result = extractFromString(path, """ - void f() { - do { - goto a; - } while (true); - - a: - while (true) { - break; - } - - for (;;) { - continue; - } - return; - } - """); - System.out.println(TokenPrinter.printTokens(result.tokens(), result.file())); - assertTokenTypes(result.tokens(), CPPTokenType.FUNCTION_BEGIN, CPPTokenType.DO_BEGIN, CPPTokenType.GOTO, CPPTokenType.DO_END, - CPPTokenType.WHILE_BEGIN, CPPTokenType.BREAK, CPPTokenType.WHILE_END, CPPTokenType.FOR_BEGIN, CPPTokenType.CONTINUE, - CPPTokenType.FOR_END, CPPTokenType.RETURN, CPPTokenType.FUNCTION_END); - - } - - @ParameterizedTest - @ValueSource(strings = {"this->myMethod(v)", "MyClass::myMethod(v)", "myMethod(v)", "m.myMethod(v)"}) - void testFunctionCalls(String expression, @TempDir Path path) { - TokenResult result = extractFromString(path, """ - void a(string v) { - %s; - } - """.formatted(expression)); - System.out.println(TokenPrinter.printTokens(result.tokens(), result.file())); - assertTokenTypes(result.tokens(), CPPTokenType.FUNCTION_BEGIN, CPPTokenType.VARDEF, CPPTokenType.APPLY, CPPTokenType.FUNCTION_END); - } - - @Test - void testIfElse(@TempDir Path path) { - // test extraction of if/else constructs - TokenResult result = extractFromString(path, """ - void a(int a, int b, int x, int y) { - if (a < b) { - x = 5; - } else if (a > b) { - { - y = 10; - } - x = y + b; - } else { - y = -20; - } - } - """); - System.out.println(TokenPrinter.printTokens(result.tokens(), result.file())); - assertTokenTypes(result.tokens(), CPPTokenType.FUNCTION_BEGIN, CPPTokenType.VARDEF, CPPTokenType.VARDEF, CPPTokenType.VARDEF, - CPPTokenType.VARDEF, CPPTokenType.IF_BEGIN, CPPTokenType.ASSIGN, CPPTokenType.ELSE, CPPTokenType.IF_BEGIN, CPPTokenType.ASSIGN, - CPPTokenType.ASSIGN, CPPTokenType.ELSE, CPPTokenType.ASSIGN, CPPTokenType.IF_END, CPPTokenType.IF_END, CPPTokenType.FUNCTION_END); - } - - @Test - void testDoubleArrayDeclaration(@TempDir Path path) { - // ensure NEWARRAY is extracted - TokenResult result = extractFromString(path, """ - double* b = new double[10]; - """); - System.out.println(TokenPrinter.printTokens(result.tokens(), result.file())); - assertTokenTypes(result.tokens(), CPPTokenType.VARDEF, CPPTokenType.ASSIGN, CPPTokenType.NEWARRAY); - } - - @Test - void testFunctionCallInAssignmentOutsideFunction(@TempDir Path path) { - // test function call extraction in an assignment context outside a function body at top-level - TokenResult result = extractFromString(path, """ - int x = square(2); - """); - System.out.println(TokenPrinter.printTokens(result.tokens(), result.file())); - assertTokenTypes(result.tokens(), CPPTokenType.VARDEF, CPPTokenType.ASSIGN, CPPTokenType.APPLY); - } - - @Test - void testFunctionCallInAssignmentInsideClassOutsideFunction(@TempDir Path path) { - // test function call extraction in an assignment context outside a function body in a class - TokenResult result = extractFromString(path, """ - class A { - int x = square(3); - }; - """); - System.out.println(TokenPrinter.printTokens(result.tokens(), result.file())); - assertTokenTypes(result.tokens(), CPPTokenType.CLASS_BEGIN, CPPTokenType.VARDEF, CPPTokenType.ASSIGN, CPPTokenType.APPLY, - CPPTokenType.CLASS_END); - } - - @Test - void testUnion(@TempDir Path path) { - // ensure union is extracted - TokenResult result = extractFromString(path, """ - union S { - std::int32_t n; - std::uint16_t s[2]; - std::uint8_t c; - }; - """); - System.out.println(TokenPrinter.printTokens(result.tokens(), result.file())); - assertTokenTypes(result.tokens(), CPPTokenType.UNION_BEGIN, CPPTokenType.VARDEF, CPPTokenType.VARDEF, CPPTokenType.VARDEF, - CPPTokenType.UNION_END); - } - - @Test - void testArrayInit(@TempDir Path path) { - // ensure { and } are extracted - TokenResult result = extractFromString(path, """ - int a[] = {1, 2, 3}; - int b[] {1, 2, 3}; - """); - System.out.println(TokenPrinter.printTokens(result.tokens(), result.file())); - assertTokenTypes(result.tokens(), CPPTokenType.VARDEF, CPPTokenType.ASSIGN, CPPTokenType.BRACED_INIT_BEGIN, CPPTokenType.BRACED_INIT_END, - CPPTokenType.VARDEF, CPPTokenType.BRACED_INIT_BEGIN, CPPTokenType.BRACED_INIT_END); - } - - static void assertTokenTypes(List tokens, TokenType... types) { - for (int i = 0; i < tokens.size(); i++) { - Token token = tokens.get(i); - if (token.getType() == SharedTokenType.FILE_END) { - assertEquals(i, types.length); - return; - } - assertEquals(types[i], token.getType(), "Unexpected token at index " + i); - } - } - - TokenResult extractFromString(@TempDir Path path, String content) { - Path filePath = path.resolve("content.cpp"); - try { - Files.writeString(filePath, content); - } catch (IOException e) { - throw new TestAbortedException("Failed to write temp file", e); - } - CPPLanguage language = new CPPLanguage(); - List tokens; - try { - tokens = language.parse(Set.of(filePath.toFile())); - } catch (ParsingException e) { - throw new TestAbortedException("Failed to extract tokens", e); - } - return new TokenResult(tokens, filePath.toFile()); - } - - record TokenResult(List tokens, File file) { - } -} \ No newline at end of file diff --git a/languages/cpp2/src/test/resources/de/jplag/cpp2/CallOutsideMethodInClass.cpp b/languages/cpp2/src/test/resources/de/jplag/cpp2/CallOutsideMethodInClass.cpp new file mode 100644 index 000000000..847f41942 --- /dev/null +++ b/languages/cpp2/src/test/resources/de/jplag/cpp2/CallOutsideMethodInClass.cpp @@ -0,0 +1,3 @@ +class A { + int x = square(3); +}; \ No newline at end of file diff --git a/languages/cpp2/src/test/resources/de/jplag/cpp2/FunctionCall.cpp b/languages/cpp2/src/test/resources/de/jplag/cpp2/FunctionCall.cpp new file mode 100644 index 000000000..8808bd9c0 --- /dev/null +++ b/languages/cpp2/src/test/resources/de/jplag/cpp2/FunctionCall.cpp @@ -0,0 +1,6 @@ +void f() { + b->funCall(); + C::funCall(); + funCall(); + a.funCall(); +} \ No newline at end of file diff --git a/languages/cpp2/src/test/resources/de/jplag/cpp2/IfElse.cpp b/languages/cpp2/src/test/resources/de/jplag/cpp2/IfElse.cpp new file mode 100644 index 000000000..8410214c2 --- /dev/null +++ b/languages/cpp2/src/test/resources/de/jplag/cpp2/IfElse.cpp @@ -0,0 +1,12 @@ +void a(int a, int b, int x, int y) { + if (a < b) { + x = 5; + } else if (a > b) { + { + y = 10; + } + x = y + b; + } else { + y = -20; + } +} \ No newline at end of file diff --git a/languages/cpp2/src/test/resources/de/jplag/cpp2/IntArray.cpp b/languages/cpp2/src/test/resources/de/jplag/cpp2/IntArray.cpp new file mode 100644 index 000000000..e78822834 --- /dev/null +++ b/languages/cpp2/src/test/resources/de/jplag/cpp2/IntArray.cpp @@ -0,0 +1,2 @@ +int a[] = {1, 2, 3}; +int b[] {1, 2, 3}; \ No newline at end of file diff --git a/languages/cpp2/src/test/resources/de/jplag/cpp2/Loop.cpp b/languages/cpp2/src/test/resources/de/jplag/cpp2/Loop.cpp new file mode 100644 index 000000000..ff20d1a49 --- /dev/null +++ b/languages/cpp2/src/test/resources/de/jplag/cpp2/Loop.cpp @@ -0,0 +1,15 @@ +void f() { + do { + goto a; + } while (true); + + a: + while (true) { + break; + } + + for (;;) { + continue; + } + return; +} \ No newline at end of file diff --git a/languages/cpp2/src/test/resources/de/jplag/cpp2/Union.cpp b/languages/cpp2/src/test/resources/de/jplag/cpp2/Union.cpp new file mode 100644 index 000000000..0134add2d --- /dev/null +++ b/languages/cpp2/src/test/resources/de/jplag/cpp2/Union.cpp @@ -0,0 +1,5 @@ +union S { + std::int32_t n; + std::uint16_t s[2]; + std::uint8_t c; +}; \ No newline at end of file diff --git a/languages/cpp2/src/test/resources/de/jplag/cpp2/bc6h_enc.h b/languages/cpp2/src/test/resources/de/jplag/cpp2/bc6h_enc.h new file mode 100644 index 000000000..35e250237 --- /dev/null +++ b/languages/cpp2/src/test/resources/de/jplag/cpp2/bc6h_enc.h @@ -0,0 +1,3667 @@ +//Taken from https://github.com/0xc0de/bc6h_enc modified slightly to work with the tests + +/* +bc6h_enc -- https://github.com/0xc0de/bc6h_enc + + Single file library for BC6H compression with no external dependencies. + + The code is based on BC6HBC7.cpp from DirectXTex and localized into a single header library + with no external dependencies. + + CREDITS: + Alexander Samusev (0xc0de) + + Do this: + #define BC6H_ENC_IMPLEMENTATION + before you include this file in *one* C++ file to create the implementation. + + // i.e. it should look like this: + #include ... + #include ... + #include ... + #define BC6H_ENC_IMPLEMENTATION + #include "bc6h_enc.h" + + You can define: + - for debug logging: + #define BC6H_LOG(s) YourPrint(s) + - for asserts: + #define BC6H_ASSERT(expression) YourAssert(expression) + - to override float<->half packing: + #define BC6H_HALF_TO_FLOAT(h) YourImpl(h) + #define BC6H_FLOAT_TO_HALF(f) YourImpl(f) + + + Public interface: + bc6h_enc::DecodeBC6HU(void* pDest, const void* pSrc) + bc6h_enc::DecodeBC6HS(void* pDest, const void* pSrc) + bc6h_enc::EncodeBC6HU(void* pDest, const void* pSrc) + bc6h_enc::EncodeBC6HS(void* pDest, const void* pSrc) + + LICENSE + ----------------------------------------------------------------------------------- + MIT License + + Copyright (c) 2022 Alexander Samusev + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + ----------------------------------------------------------------------------------- + DirectXTex + The MIT License (MIT) + + Copyright (c) 2011-2022 Microsoft Corp + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be included in all copies + or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +----------------------------------------------------------------------------------- + Branch-free implementation of half-precision (16 bit) floating point + Copyright 2006 Mike Acton + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE + ----------------------------------------------------------------------------------- +*/ + +#ifndef BC6H_ENC_IMPLEMENTATION + +#ifndef BC6H_ENC_INCLUDED +#define BC6H_ENC_INCLUDED + +namespace bc6h_enc +{ +void DecodeBC6HU(void* pDest, const void* pSrc) noexcept; +void DecodeBC6HS(void* pDest, const void* pSrc) noexcept; +void EncodeBC6HU(void* pDest, const void* pSrc) noexcept; +void EncodeBC6HS(void* pDest, const void* pSrc) noexcept; +} // namespace bc6h_enc + +#endif + +#else + +#include + +# ifdef BC6H_SSE_INTRINSICS +# include +# endif + +# ifdef BC6H_ARM_NEON_INTRINSICS +# include +# endif + +#ifndef BC6H_ASSERT +# define BC6H_ASSERT(expression) +# define BC6H_ASSERT_UNDEF +#endif + +#ifndef FLT_MAX +#define FLT_MAX 3.402823466e+38F // max value +#endif + +#ifndef FLT_MIN +#define FLT_MIN 1.175494351e-38F // min normalized positive value +#endif + +#define BC6H_INLINE inline + +namespace bc6h_enc +{ + +namespace Impl +{ + +using HALF = uint16_t; + +#if !defined(BC6H_HALF_TO_FLOAT) +// Fast half to float conversion based on: +// http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf +struct FastHalfToFloat +{ + FastHalfToFloat() + { + m_MantissaTable[0] = 0; + for (int i = 1; i < 1024; i++) + { + uint32_t m = i << 13; + uint32_t e = 0; + while ((m & 0x00800000) == 0) + { + e -= 0x00800000; + m <<= 1; + } + m &= ~0x00800000; + e += 0x38800000; + m_MantissaTable[i] = m | e; + } + for (int i = 1024; i < 2048; i++) + m_MantissaTable[i] = (i - 1024) << 13; + m_ExponentTable[0] = 0; + for (int i = 1; i < 31; i++) + m_ExponentTable[i] = 0x38000000 + (i << 23); + m_ExponentTable[31] = 0x7f800000; + m_ExponentTable[32] = 0x80000000; + for (int i = 33; i < 63; i++) + m_ExponentTable[i] = 0xb8000000 + ((i - 32) << 23); + m_ExponentTable[63] = 0xff800000; + m_OffsetTable[0] = 0; + for (int i = 1; i < 32; i++) + m_OffsetTable[i] = 1024; + m_OffsetTable[32] = 0; + for (int i = 33; i < 64; i++) + m_OffsetTable[i] = 1024; + } + uint32_t m_MantissaTable[2048]; + uint32_t m_ExponentTable[64]; + uint32_t m_OffsetTable[64]; + + BC6H_INLINE uint32_t Convert(uint16_t h) const + { + uint32_t exp = h >> 10; + return m_MantissaTable[m_OffsetTable[exp] + (h & 0x3ff)] + m_ExponentTable[exp]; + } +}; +FastHalfToFloat g_FastHalfToFloat; + +# define BC6H_HALF_TO_FLOAT g_FastHalfToFloat.Convert +# define BC6H_HALF_TO_FLOAT_UNDEF + +#endif + +#if !defined(BC6H_FLOAT_TO_HALF) + +# ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable : 4146) // unary minus operator applied to unsigned type, result still unsigned +# endif + +BC6H_INLINE uint32_t _uint32_li(uint32_t a) { return (a); } +BC6H_INLINE uint32_t _uint32_dec(uint32_t a) { return (a - 1); } +BC6H_INLINE uint32_t _uint32_inc(uint32_t a) { return (a + 1); } +BC6H_INLINE uint32_t _uint32_not(uint32_t a) { return (~a); } +BC6H_INLINE uint32_t _uint32_neg(uint32_t a) { return (-a); } +BC6H_INLINE uint32_t _uint32_ext(uint32_t a) { return (((int32_t)a) >> 31); } +BC6H_INLINE uint32_t _uint32_and(uint32_t a, uint32_t b) { return (a & b); } +BC6H_INLINE uint32_t _uint32_andc(uint32_t a, uint32_t b) { return (a & ~b); } +BC6H_INLINE uint32_t _uint32_or(uint32_t a, uint32_t b) { return (a | b); } +BC6H_INLINE uint32_t _uint32_srl(uint32_t a, int sa) { return (a >> sa); } +BC6H_INLINE uint32_t _uint32_sll(uint32_t a, int sa) { return (a << sa); } +BC6H_INLINE uint32_t _uint32_add(uint32_t a, uint32_t b) { return (a + b); } +BC6H_INLINE uint32_t _uint32_sub(uint32_t a, uint32_t b) { return (a - b); } +BC6H_INLINE uint32_t _uint32_sels(uint32_t test, uint32_t a, uint32_t b) +{ + const uint32_t mask = _uint32_ext(test); + const uint32_t sel_a = _uint32_and(a, mask); + const uint32_t sel_b = _uint32_andc(b, mask); + const uint32_t result = _uint32_or(sel_a, sel_b); + return (result); +} +BC6H_INLINE uint16_t half_from_float(uint32_t f) +{ + const uint32_t one = _uint32_li(0x00000001); + const uint32_t f_s_mask = _uint32_li(0x80000000); + const uint32_t f_e_mask = _uint32_li(0x7f800000); + const uint32_t f_m_mask = _uint32_li(0x007fffff); + const uint32_t f_m_hidden_bit = _uint32_li(0x00800000); + const uint32_t f_m_round_bit = _uint32_li(0x00001000); + const uint32_t f_snan_mask = _uint32_li(0x7fc00000); + const uint32_t f_e_pos = _uint32_li(0x00000017); + const uint32_t h_e_pos = _uint32_li(0x0000000a); + const uint32_t h_e_mask = _uint32_li(0x00007c00); + const uint32_t h_snan_mask = _uint32_li(0x00007e00); + const uint32_t h_e_mask_value = _uint32_li(0x0000001f); + const uint32_t f_h_s_pos_offset = _uint32_li(0x00000010); + const uint32_t f_h_bias_offset = _uint32_li(0x00000070); + const uint32_t f_h_m_pos_offset = _uint32_li(0x0000000d); + const uint32_t h_nan_min = _uint32_li(0x00007c01); + const uint32_t f_h_e_biased_flag = _uint32_li(0x0000008f); + const uint32_t f_s = _uint32_and(f, f_s_mask); + const uint32_t f_e = _uint32_and(f, f_e_mask); + const uint16_t h_s = _uint32_srl(f_s, f_h_s_pos_offset); + const uint32_t f_m = _uint32_and(f, f_m_mask); + const uint16_t f_e_amount = _uint32_srl(f_e, f_e_pos); + const uint32_t f_e_half_bias = _uint32_sub(f_e_amount, f_h_bias_offset); + const uint32_t f_snan = _uint32_and(f, f_snan_mask); + const uint32_t f_m_round_mask = _uint32_and(f_m, f_m_round_bit); + const uint32_t f_m_round_offset = _uint32_sll(f_m_round_mask, one); + const uint32_t f_m_rounded = _uint32_add(f_m, f_m_round_offset); + const uint32_t f_m_denorm_sa = _uint32_sub(one, f_e_half_bias); + const uint32_t f_m_with_hidden = _uint32_or(f_m_rounded, f_m_hidden_bit); + const uint32_t f_m_denorm = _uint32_srl(f_m_with_hidden, f_m_denorm_sa); + const uint32_t h_m_denorm = _uint32_srl(f_m_denorm, f_h_m_pos_offset); + const uint32_t f_m_rounded_overflow = _uint32_and(f_m_rounded, f_m_hidden_bit); + const uint32_t m_nan = _uint32_srl(f_m, f_h_m_pos_offset); + const uint32_t h_em_nan = _uint32_or(h_e_mask, m_nan); + const uint32_t h_e_norm_overflow_offset = _uint32_inc(f_e_half_bias); + const uint32_t h_e_norm_overflow = _uint32_sll(h_e_norm_overflow_offset, h_e_pos); + const uint32_t h_e_norm = _uint32_sll(f_e_half_bias, h_e_pos); + const uint32_t h_m_norm = _uint32_srl(f_m_rounded, f_h_m_pos_offset); + const uint32_t h_em_norm = _uint32_or(h_e_norm, h_m_norm); + const uint32_t is_h_ndenorm_msb = _uint32_sub(f_h_bias_offset, f_e_amount); + const uint32_t is_f_e_flagged_msb = _uint32_sub(f_h_e_biased_flag, f_e_half_bias); + const uint32_t is_h_denorm_msb = _uint32_not(is_h_ndenorm_msb); + const uint32_t is_f_m_eqz_msb = _uint32_dec(f_m); + const uint32_t is_h_nan_eqz_msb = _uint32_dec(m_nan); + const uint32_t is_f_inf_msb = _uint32_and(is_f_e_flagged_msb, is_f_m_eqz_msb); + const uint32_t is_f_nan_underflow_msb = _uint32_and(is_f_e_flagged_msb, is_h_nan_eqz_msb); + const uint32_t is_e_overflow_msb = _uint32_sub(h_e_mask_value, f_e_half_bias); + const uint32_t is_h_inf_msb = _uint32_or(is_e_overflow_msb, is_f_inf_msb); + const uint32_t is_f_nsnan_msb = _uint32_sub(f_snan, f_snan_mask); + const uint32_t is_m_norm_overflow_msb = _uint32_neg(f_m_rounded_overflow); + const uint32_t is_f_snan_msb = _uint32_not(is_f_nsnan_msb); + const uint32_t h_em_overflow_result = _uint32_sels(is_m_norm_overflow_msb, h_e_norm_overflow, h_em_norm); + const uint32_t h_em_nan_result = _uint32_sels(is_f_e_flagged_msb, h_em_nan, h_em_overflow_result); + const uint32_t h_em_nan_underflow_result = _uint32_sels(is_f_nan_underflow_msb, h_nan_min, h_em_nan_result); + const uint32_t h_em_inf_result = _uint32_sels(is_h_inf_msb, h_e_mask, h_em_nan_underflow_result); + const uint32_t h_em_denorm_result = _uint32_sels(is_h_denorm_msb, h_m_denorm, h_em_inf_result); + const uint32_t h_em_snan_result = _uint32_sels(is_f_snan_msb, h_snan_mask, h_em_denorm_result); + const uint32_t h_result = _uint32_or(h_s, h_em_snan_result); + return (uint16_t)(h_result); +} +# ifdef _MSC_VER +# pragma warning(pop) +# endif + +# define BC6H_FLOAT_TO_HALF half_from_float +# define BC6H_FLOAT_TO_HALF_UNDEF + +#endif + +# if defined(BC6H_SSE_INTRINSICS) +using XMVECTOR = __m128; +# elif defined(BC6H_ARM_NEON_INTRINSICS) +using XMVECTOR = float32x4_t; +# else +struct XMVECTOR +{ + float x; + float y; + float z; + float w; +}; +# endif + +// Fix-up for (1st-3rd) XMVECTOR parameters that are pass-in-register for x86, ARM, ARM64, and vector call; by reference otherwise +# if defined(BC6H_SSE_INTRINSICS) || defined(BC6H_NEON_INTRINSICS) +typedef const XMVECTOR FXMVECTOR; +# else +typedef const XMVECTOR& FXMVECTOR; +# endif + +struct XMINT4 +{ + int32_t x; + int32_t y; + int32_t z; + int32_t w; +}; +struct XMHALF4 +{ + HALF x; + HALF y; + HALF z; + HALF w; +}; +struct XMFLOAT4 +{ + float x; + float y; + float z; + float w; +}; +BC6H_INLINE float XMConvertHalfToFloat(HALF h) noexcept +{ +# if defined(BC6H_SSE_INTRINSICS) + __m128i V1 = _mm_cvtsi32_si128(static_cast(h)); + __m128 V2 = _mm_cvtph_ps(V1); + return _mm_cvtss_f32(V2); +# elif defined(BC6H_ARM_NEON_INTRINSICS) + uint16x4_t vHalf = vdup_n_u16(h); + float32x4_t vFloat = vcvt_f32_f16(vreinterpret_f16_u16(vHalf)); + return vgetq_lane_f32(vFloat, 0); +# else + uint32_t f = BC6H_HALF_TO_FLOAT(h); + return *reinterpret_cast(&f); +# endif +} +BC6H_INLINE HALF XMConvertFloatToHalf(float f) noexcept +{ + return BC6H_FLOAT_TO_HALF(*reinterpret_cast(&f)); +} + + struct alignas(16) XMFLOAT4A : public XMFLOAT4 +{ + using XMFLOAT4::XMFLOAT4; +}; + + BC6H_INLINE void XMStoreFloat4A(XMFLOAT4A* pDestination, FXMVECTOR V) noexcept +{ + BC6H_ASSERT((reinterpret_cast(pDestination) & 0xF) == 0); + +# if defined(BC6H_SSE_INTRINSICS) + _mm_store_ps(&pDestination->x, V); +# elif defined(BC6H_ARM_NEON_INTRINSICS) +# if defined(_MSC_VER) && !defined(__clang__) + vst1q_f32_ex(reinterpret_cast(pDestination), V, 128); +# else + vst1q_f32(reinterpret_cast(pDestination), V); +# endif +# else + pDestination->x = V.x; + pDestination->y = V.y; + pDestination->z = V.z; + pDestination->w = V.w; +# endif +} +BC6H_INLINE void XMStoreHalf4(XMHALF4* pDestination, FXMVECTOR V) noexcept +{ +//# if defined(BC6H_SSE_INTRINSICS /* _XM_F16C_INTRINSICS_*/)// && !defined(_XM_NO_INTRINSICS_) +# if defined(BC6H_SSE_INTRINSICS) + __m128i V1 = _mm_cvtps_ph(V, _MM_FROUND_TO_NEAREST_INT); + _mm_storel_epi64(reinterpret_cast<__m128i*>(pDestination), V1); +# else + pDestination->x = XMConvertFloatToHalf(V.x); + pDestination->y = XMConvertFloatToHalf(V.y); + pDestination->z = XMConvertFloatToHalf(V.z); + pDestination->w = XMConvertFloatToHalf(V.w); +# endif +} +BC6H_INLINE XMVECTOR XMLoadFloat4(const XMFLOAT4* pSource) noexcept +{ +# if defined BC6H_SSE_INTRINSICS + return _mm_loadu_ps(&pSource->x); +# elif defined BC6H_ARM_NEON_INTRINSIC + return vld1q_f32(reinterpret_cast(pSource)); +# else + XMVECTOR V; + V.x = pSource->x; + V.y = pSource->y; + V.z = pSource->z; + V.w = pSource->w; + return V; +# endif +} +BC6H_INLINE XMVECTOR XMVectorSubtract(FXMVECTOR V1, FXMVECTOR V2) noexcept +{ +#if defined(BC6H_SSE_INTRINSICS) + return _mm_sub_ps(V1, V2); +#elif defined(BC6H_ARM_NEON_INTRINSIC) + return vsubq_f32(V1, V2); +#else + return {V1.x - V2.x, V1.y - V2.y, V1.z - V2.z, V1.w - V2.w}; +#endif +} +struct alignas(16) XMVECTORU32 +{ + union + { + uint32_t u[4]; + XMVECTOR v; + }; + + BC6H_INLINE operator XMVECTOR() const noexcept { return v; } + +# if defined(BC6H_SSE_INTRINSICS) + BC6H_INLINE operator __m128i() const noexcept + { + return _mm_castps_si128(v); + } + BC6H_INLINE operator __m128d() const noexcept { return _mm_castps_pd(v); } +# elif defined(BC6H_ARM_NEON_INTRINSIC) && defined(__GNUC__) + BC6H_INLINE operator int32x4_t() const noexcept + { + return vreinterpretq_s32_f32(v); + } + BC6H_INLINE operator uint32x4_t() const noexcept { return vreinterpretq_u32_f32(v); } +# endif +}; + +const XMVECTORU32 g_XMMask3 = {{{0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000}}}; + +# if defined(BC6H_SSE_INTRINSICS) || defined(BC6H_ARM_NEON_INTRINSIC) + +// SSE2 +//BC6H_INLINE XMVECTOR XMVector3Dot(FXMVECTOR V1, FXMVECTOR V2) +//{ +// XMVECTOR vTemp = _mm_mul_ps(V1, V2); +// vTemp = _mm_and_ps(vTemp, g_XMMask3); +// vTemp = _mm_hadd_ps(vTemp, vTemp); +// return _mm_hadd_ps(vTemp, vTemp); +//} +// SSE3 +BC6H_INLINE XMVECTOR XMVector3Dot(FXMVECTOR V1, FXMVECTOR V2) +{ + return _mm_dp_ps(V1, V2, 0x7f); +} + +BC6H_INLINE float XMVectorGetX(FXMVECTOR V) noexcept +{ +# if defined(BC6H_SSE_INTRINSICS) + return _mm_cvtss_f32(V); +# elif defined(BC6H_ARM_NEON_INTRINSIC) + return vgetq_lane_f32(V, 0); +# endif +} +BC6H_INLINE float XMVectorDot(FXMVECTOR a, FXMVECTOR b) +{ + return XMVectorGetX(XMVector3Dot(a, b)); +} +#else +BC6H_INLINE float XMVectorDot(FXMVECTOR a, FXMVECTOR b) +{ + // XMVectorGetX(XMVector3Dot(a, b)) + return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; +} +#endif + +BC6H_INLINE XMVECTOR XMLoadSInt4(const XMINT4* pSource) noexcept +{ +# if defined(BC6H_SSE_INTRINSICS) + __m128i V = _mm_loadu_si128(reinterpret_cast(pSource)); + return _mm_cvtepi32_ps(V); +# elif defined(BC6H_ARM_NEON_INTRINSICS_) + int32x4_t v = vld1q_s32(reinterpret_cast(pSource)); + return vcvtq_f32_s32(v); +# else + XMVECTOR V; + V.x = static_cast(pSource->x); + V.y = static_cast(pSource->y); + V.z = static_cast(pSource->z); + V.w = static_cast(pSource->w); + return V; +# endif +} + +template +const T& std__max(const T& a, const T& b) noexcept +{ + return (a < b) ? b : a; +} + +template +const T& std__min(const T& a, const T& b) noexcept +{ + return (b < a) ? b : a; +} + +template +void std__swap(T& a, T& b) noexcept +{ + T temp(a); + a = b; + b = temp; +} + +class LDRColorA{}; + +class HDRColorA { +public: + float r, g, b, a; + + HDRColorA() = default; + HDRColorA(float _r, float _g, float _b, float _a) noexcept : + r(_r), g(_g), b(_b), a(_a) {} + HDRColorA(const HDRColorA& c) noexcept : + r(c.r), g(c.g), b(c.b), a(c.a) {} + + // binary operators + HDRColorA operator+(const HDRColorA& c) const noexcept + { + return HDRColorA(r + c.r, g + c.g, b + c.b, a + c.a); + } + + HDRColorA operator-(const HDRColorA& c) const noexcept + { + return HDRColorA(r - c.r, g - c.g, b - c.b, a - c.a); + } + + HDRColorA operator*(float f) const noexcept + { + return HDRColorA(r * f, g * f, b * f, a * f); + } + + HDRColorA operator/(float f) const noexcept + { + const float fInv = 1.0f / f; + return HDRColorA(r * fInv, g * fInv, b * fInv, a * fInv); + } + + float operator*(const HDRColorA& c) const noexcept + { + return r * c.r + g * c.g + b * c.b + a * c.a; + } + + // assignment operators + HDRColorA& operator+=(const HDRColorA& c) noexcept + { + r += c.r; + g += c.g; + b += c.b; + a += c.a; + return *this; + } + + HDRColorA& operator-=(const HDRColorA& c) noexcept + { + r -= c.r; + g -= c.g; + b -= c.b; + a -= c.a; + return *this; + } + + HDRColorA& operator*=(float f) noexcept + { + r *= f; + g *= f; + b *= f; + a *= f; + return *this; + } + + HDRColorA& operator/=(float f) noexcept + { + const float fInv = 1.0f / f; + r *= fInv; + g *= fInv; + b *= fInv; + a *= fInv; + return *this; + } + + HDRColorA& Clamp(float fMin, float fMax) noexcept + { + r = std__min(fMax, std__max(fMin, r)); + g = std__min(fMax, std__max(fMin, g)); + b = std__min(fMax, std__max(fMin, b)); + a = std__min(fMax, std__max(fMin, a)); + return *this; + } + + HDRColorA(const LDRColorA& c) noexcept; + HDRColorA& operator=(const LDRColorA& c) noexcept; +}; + +//------------------------------------------------------------------------------------- +// Constants +//------------------------------------------------------------------------------------- + +constexpr uint16_t F16S_MASK = 0x8000; // f16 sign mask +constexpr uint16_t F16EM_MASK = 0x7fff; // f16 exp & mantissa mask +constexpr uint16_t F16MAX = 0x7bff; // MAXFLT bit pattern for XMHALF + +constexpr size_t BC6H_NUM_PIXELS_PER_BLOCK = 16; +constexpr size_t BC6H_MAX_REGIONS = 2; +constexpr size_t BC6H_MAX_INDICES = 16; +constexpr size_t BC6H_NUM_CHANNELS = 3; +constexpr size_t BC6H_MAX_SHAPES = 32; +constexpr int32_t BC6H_WEIGHT_MAX = 64; +constexpr uint32_t BC6H_WEIGHT_SHIFT = 6; +constexpr int32_t BC6H_WEIGHT_ROUND = 32; + +constexpr float fEpsilon = (0.25f / 64.0f) * (0.25f / 64.0f); +constexpr float pC3[] = {2.0f / 2.0f, 1.0f / 2.0f, 0.0f / 2.0f}; +constexpr float pD3[] = {0.0f / 2.0f, 1.0f / 2.0f, 2.0f / 2.0f}; +constexpr float pC4[] = {3.0f / 3.0f, 2.0f / 3.0f, 1.0f / 3.0f, 0.0f / 3.0f}; +constexpr float pD4[] = {0.0f / 3.0f, 1.0f / 3.0f, 2.0f / 3.0f, 3.0f / 3.0f}; + +// Partition, Shape, Pixel (index into 4x4 block) +const uint8_t g_aPartitionTable[2][32][16] = + { + { + // 1 Region case has no subsets (all 0) + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + }, + + { + // BC6H/BC7 Partition Set for 2 Subsets + {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1}, // Shape 0 + {0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1}, // Shape 1 + {0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1}, // Shape 2 + {0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1}, // Shape 3 + {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1}, // Shape 4 + {0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1}, // Shape 5 + {0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1}, // Shape 6 + {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1}, // Shape 7 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1}, // Shape 8 + {0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // Shape 9 + {0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1}, // Shape 10 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1}, // Shape 11 + {0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // Shape 12 + {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}, // Shape 13 + {0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // Shape 14 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1}, // Shape 15 + {0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1}, // Shape 16 + {0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, // Shape 17 + {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0}, // Shape 18 + {0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0}, // Shape 19 + {0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, // Shape 20 + {0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0}, // Shape 21 + {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0}, // Shape 22 + {0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1}, // Shape 23 + {0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0}, // Shape 24 + {0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0}, // Shape 25 + {0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0}, // Shape 26 + {0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0}, // Shape 27 + {0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0}, // Shape 28 + {0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0}, // Shape 29 + {0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0}, // Shape 30 + {0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0} // Shape 31 + } +}; + +// Partition, Shape, Fixup +const uint8_t g_aFixUp[2][32][3] = + { + { + // No fix-ups for 1st subset for BC6H or BC7 + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}, + {0, 0, 0} + }, + + { + // BC6H/BC7 Partition Set Fixups for 2 Subsets + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 15, 0}, + {0, 2, 0}, + {0, 8, 0}, + {0, 2, 0}, + {0, 2, 0}, + {0, 8, 0}, + {0, 8, 0}, + {0, 15, 0}, + {0, 2, 0}, + {0, 8, 0}, + {0, 2, 0}, + {0, 2, 0}, + {0, 8, 0}, + {0, 8, 0}, + {0, 2, 0}, + {0, 2, 0} + } +}; + +const int g_aWeights3[] = {0, 9, 18, 27, 37, 46, 55, 64}; +const int g_aWeights4[] = {0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64}; + +class LDRColorA +{ +public: + uint8_t r, g, b, a; + + LDRColorA() = default; + LDRColorA(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t _a) noexcept : + r(_r), g(_g), b(_b), a(_a) {} + + const uint8_t& operator[](size_t uElement) const noexcept + { + switch (uElement) + { + case 0: return r; + case 1: return g; + case 2: return b; + case 3: return a; + default: BC6H_ASSERT(false); return r; + } + } + + uint8_t& operator[](size_t uElement) noexcept + { + switch (uElement) + { + case 0: return r; + case 1: return g; + case 2: return b; + case 3: return a; + default: BC6H_ASSERT(false); return r; + } + } + + LDRColorA operator=(const HDRColorA& c) noexcept + { + LDRColorA ret; + HDRColorA tmp(c); + tmp = tmp.Clamp(0.0f, 1.0f) * 255.0f; + ret.r = uint8_t(tmp.r + 0.001f); + ret.g = uint8_t(tmp.g + 0.001f); + ret.b = uint8_t(tmp.b + 0.001f); + ret.a = uint8_t(tmp.a + 0.001f); + return ret; + } +}; + +static_assert(sizeof(LDRColorA) == 4, "Unexpected packing"); + +struct LDREndPntPair +{ + LDRColorA A; + LDRColorA B; +}; + +BC6H_INLINE HDRColorA::HDRColorA(const LDRColorA& c) noexcept +{ + r = float(c.r) * (1.0f / 255.0f); + g = float(c.g) * (1.0f / 255.0f); + b = float(c.b) * (1.0f / 255.0f); + a = float(c.a) * (1.0f / 255.0f); +} + +BC6H_INLINE HDRColorA& HDRColorA::operator=(const LDRColorA& c) noexcept +{ + r = static_cast(c.r); + g = static_cast(c.g); + b = static_cast(c.b); + a = static_cast(c.a); + return *this; +} + +class INTColor +{ +public: + int r, g, b; + int pad; + +public: + INTColor() = default; + INTColor(int nr, int ng, int nb) noexcept : + r(nr), g(ng), b(nb), pad(0) {} + INTColor(const INTColor& c) noexcept : + r(c.r), g(c.g), b(c.b), pad(0) {} + + INTColor& operator+=(const INTColor& c) noexcept + { + r += c.r; + g += c.g; + b += c.b; + return *this; + } + + INTColor& operator-=(const INTColor& c) noexcept + { + r -= c.r; + g -= c.g; + b -= c.b; + return *this; + } + + INTColor& operator&=(const INTColor& c) noexcept + { + r &= c.r; + g &= c.g; + b &= c.b; + return *this; + } + + int& operator[](uint8_t i) noexcept + { + BC6H_ASSERT(i < sizeof(INTColor) / sizeof(int)); + return reinterpret_cast(this)[i]; + } + + void Set(const HDRColorA& c, bool bSigned) noexcept + { + XMHALF4 aF16; + + const XMVECTOR v = XMLoadFloat4(reinterpret_cast(&c)); + XMStoreHalf4(&aF16, v); + + r = F16ToINT(aF16.x, bSigned); + g = F16ToINT(aF16.y, bSigned); + b = F16ToINT(aF16.z, bSigned); + } + + INTColor& Clamp(int iMin, int iMax) noexcept + { + r = std__min(iMax, std__max(iMin, r)); + g = std__min(iMax, std__max(iMin, g)); + b = std__min(iMax, std__max(iMin, b)); + return *this; + } + + INTColor& SignExtend(const LDRColorA& Prec) noexcept + { +#define BC6H_SIGN_EXTEND(x, nb) ((((x) & (1 << ((nb)-1))) ? ((~0) ^ ((1 << (nb)) - 1)) : 0) | (x)) + r = BC6H_SIGN_EXTEND(r, int(Prec.r)); + g = BC6H_SIGN_EXTEND(g, int(Prec.g)); + b = BC6H_SIGN_EXTEND(b, int(Prec.b)); +#undef BC6H_SIGN_EXTEND + return *this; + } + + void ToF16(HALF aF16[3], bool bSigned) const noexcept + { + aF16[0] = INT2F16(r, bSigned); + aF16[1] = INT2F16(g, bSigned); + aF16[2] = INT2F16(b, bSigned); + } + +private: + static int F16ToINT(const HALF& f, bool bSigned) noexcept + { + uint16_t input = *reinterpret_cast(&f); + int out, s; + if (bSigned) + { + s = input & F16S_MASK; + input &= F16EM_MASK; + if (input > F16MAX) out = F16MAX; + else + out = input; + out = s ? -out : out; + } + else + { + if (input & F16S_MASK) out = 0; + else + out = input; + } + return out; + } + + static HALF INT2F16(int input, bool bSigned) noexcept + { + HALF h; + uint16_t out; + if (bSigned) + { + int s = 0; + if (input < 0) + { + s = F16S_MASK; + input = -input; + } + out = uint16_t(s | input); + } + else + { + BC6H_ASSERT(input >= 0 && input <= F16MAX); + out = static_cast(input); + } + + *reinterpret_cast(&h) = out; + return h; + } +}; + +static_assert(sizeof(INTColor) == 16, "Unexpected packing"); + +struct INTEndPntPair +{ + INTColor A; + INTColor B; +}; + +template +class CBits +{ +public: + uint8_t GetBit(size_t& uStartBit) const noexcept + { + BC6H_ASSERT(uStartBit < 128); + const size_t uIndex = uStartBit >> 3; + auto const ret = static_cast((m_uBits[uIndex] >> (uStartBit - (uIndex << 3))) & 0x01); + uStartBit++; + return ret; + } + + uint8_t GetBits(size_t& uStartBit, size_t uNumBits) const noexcept + { + if (uNumBits == 0) return 0; + BC6H_ASSERT(uStartBit + uNumBits <= 128 && uNumBits <= 8); + uint8_t ret; + const size_t uIndex = uStartBit >> 3; + const size_t uBase = uStartBit - (uIndex << 3); + if (uBase + uNumBits > 8) + { + const size_t uFirstIndexBits = 8 - uBase; + const size_t uNextIndexBits = uNumBits - uFirstIndexBits; + ret = static_cast((unsigned(m_uBits[uIndex]) >> uBase) | ((unsigned(m_uBits[uIndex + 1]) & ((1u << uNextIndexBits) - 1)) << uFirstIndexBits)); + } + else + { + ret = static_cast((m_uBits[uIndex] >> uBase) & ((1 << uNumBits) - 1)); + } + BC6H_ASSERT(ret < (1 << uNumBits)); + uStartBit += uNumBits; + return ret; + } + + void SetBit(size_t& uStartBit, uint8_t uValue) noexcept + { + BC6H_ASSERT(uStartBit < 128 && uValue < 2); + size_t uIndex = uStartBit >> 3; + const size_t uBase = uStartBit - (uIndex << 3); + m_uBits[uIndex] &= ~(1 << uBase); + m_uBits[uIndex] |= uValue << uBase; + uStartBit++; + } + + void SetBits(size_t& uStartBit, size_t uNumBits, uint8_t uValue) noexcept + { + if (uNumBits == 0) + return; + BC6H_ASSERT(uStartBit + uNumBits <= 128 && uNumBits <= 8); + BC6H_ASSERT(uValue < (1 << uNumBits)); + size_t uIndex = uStartBit >> 3; + const size_t uBase = uStartBit - (uIndex << 3); + if (uBase + uNumBits > 8) + { + const size_t uFirstIndexBits = 8 - uBase; + const size_t uNextIndexBits = uNumBits - uFirstIndexBits; + m_uBits[uIndex] &= ~(((1 << uFirstIndexBits) - 1) << uBase); + m_uBits[uIndex] |= uValue << uBase; + m_uBits[uIndex + 1] &= ~((1 << uNextIndexBits) - 1); + m_uBits[uIndex + 1] |= uValue >> uFirstIndexBits; + } + else + { + m_uBits[uIndex] &= ~(((1 << uNumBits) - 1) << uBase); + m_uBits[uIndex] |= uValue << uBase; + } + uStartBit += uNumBits; + } + +private: + uint8_t m_uBits[SizeInBytes]; +}; + +// BC6H compression (16 bits per texel) +class D3DX_BC6H : private CBits<16> +{ +public: + void Decode(bool bSigned, HDRColorA* pOut) const noexcept; + void Encode(bool bSigned, const HDRColorA* const pIn) noexcept; + +private: +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4480) +#endif + enum EField : uint8_t + { NA, M, D, RX, RY, RZ, GW, GX, GY, GZ, BW, BX, BY, BZ, }; +#ifdef _MSC_VER +#pragma warning(pop) +#endif + + struct ModeDescriptor + { + EField m_eField; + uint8_t m_uBit; + }; + + struct ModeInfo + { + uint8_t uMode; + uint8_t uPartitions; + bool bTransformed; + uint8_t uIndexPrec; + LDRColorA RGBAPrec[BC6H_MAX_REGIONS][2]; + }; + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4512) +#endif + struct EncodeParams + { + float fBestErr; + const bool bSigned; + uint8_t uMode; + uint8_t uShape; + const HDRColorA* const aHDRPixels; + INTEndPntPair aUnqEndPts[BC6H_MAX_SHAPES][BC6H_MAX_REGIONS]; + INTColor aIPixels[BC6H_NUM_PIXELS_PER_BLOCK]; + + EncodeParams(const HDRColorA* const aOriginal, bool bSignedFormat) noexcept : + fBestErr(FLT_MAX), bSigned(bSignedFormat), uMode(0), uShape(0), aHDRPixels(aOriginal), aUnqEndPts{}, aIPixels{} + { + for (size_t i = 0; i < BC6H_NUM_PIXELS_PER_BLOCK; ++i) + { + aIPixels[i].Set(aOriginal[i], bSigned); + } + } + }; +#ifdef _MSC_VER +#pragma warning(pop) +#endif + + static int Quantize(int iValue, int prec, bool bSigned) noexcept; + static int Unquantize(int comp, uint8_t uBitsPerComp, bool bSigned) noexcept; + static int FinishUnquantize(int comp, bool bSigned) noexcept; + + static bool EndPointsFit(const EncodeParams* pEP, const INTEndPntPair aEndPts[]) noexcept; + + void GeneratePaletteQuantized(const EncodeParams* pEP, const INTEndPntPair& endPts, INTColor aPalette[]) const noexcept; + float MapColorsQuantized(const EncodeParams* pEP, const INTColor aColors[], size_t np, const INTEndPntPair& endPts) const noexcept; + float PerturbOne(const EncodeParams* pEP, const INTColor aColors[], size_t np, uint8_t ch, const INTEndPntPair& oldEndPts, INTEndPntPair& newEndPts, float fOldErr, int do_b) const noexcept; + void OptimizeOne(const EncodeParams* pEP, const INTColor aColors[], size_t np, float aOrgErr, const INTEndPntPair& aOrgEndPts, INTEndPntPair& aOptEndPts) const noexcept; + void OptimizeEndPoints(const EncodeParams* pEP, const float aOrgErr[], const INTEndPntPair aOrgEndPts[], INTEndPntPair aOptEndPts[]) const noexcept; + static void SwapIndices(const EncodeParams* pEP, INTEndPntPair aEndPts[], size_t aIndices[]) noexcept; + void AssignIndices(const EncodeParams* pEP, const INTEndPntPair aEndPts[], size_t aIndices[], float aTotErr[]) const noexcept; + void QuantizeEndPts(const EncodeParams* pEP, INTEndPntPair* qQntEndPts) const noexcept; + void EmitBlock(const EncodeParams* pEP, const INTEndPntPair aEndPts[], const size_t aIndices[]) noexcept; + void Refine(EncodeParams* pEP) noexcept; + + static void GeneratePaletteUnquantized(const EncodeParams* pEP, size_t uRegion, INTColor aPalette[]) noexcept; + float MapColors(const EncodeParams* pEP, size_t uRegion, size_t np, const size_t* auIndex) const noexcept; + float RoughMSE(EncodeParams* pEP) const noexcept; + +private: + static const ModeDescriptor ms_aDesc[][82]; + static const ModeInfo ms_aInfo[]; + static const int ms_aModeToInfo[]; +}; + +// BC6H Compression +const D3DX_BC6H::ModeDescriptor D3DX_BC6H::ms_aDesc[14][82] = + { + { + // Mode 1 (0x00) - 10 5 5 5 + {M, 0}, + {M, 1}, + {GY, 4}, + {BY, 4}, + {BZ, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {RW, 7}, + {RW, 8}, + {RW, 9}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {GW, 7}, + {GW, 8}, + {GW, 9}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BW, 7}, + {BW, 8}, + {BW, 9}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RX, 4}, + {GZ, 4}, + {GY, 0}, + {GY, 1}, + {GY, 2}, + {GY, 3}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GX, 4}, + {BZ, 0}, + {GZ, 0}, + {GZ, 1}, + {GZ, 2}, + {GZ, 3}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BX, 4}, + {BZ, 1}, + {BY, 0}, + {BY, 1}, + {BY, 2}, + {BY, 3}, + {RY, 0}, + {RY, 1}, + {RY, 2}, + {RY, 3}, + {RY, 4}, + {BZ, 2}, + {RZ, 0}, + {RZ, 1}, + {RZ, 2}, + {RZ, 3}, + {RZ, 4}, + {BZ, 3}, + {D, 0}, + {D, 1}, + {D, 2}, + {D, 3}, + {D, 4}, + }, + + { + // Mode 2 (0x01) - 7 6 6 6 + {M, 0}, + {M, 1}, + {GY, 5}, + {GZ, 4}, + {GZ, 5}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {BZ, 0}, + {BZ, 1}, + {BY, 4}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {BY, 5}, + {BZ, 2}, + {GY, 4}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BZ, 3}, + {BZ, 5}, + {BZ, 4}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RX, 4}, + {RX, 5}, + {GY, 0}, + {GY, 1}, + {GY, 2}, + {GY, 3}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GX, 4}, + {GX, 5}, + {GZ, 0}, + {GZ, 1}, + {GZ, 2}, + {GZ, 3}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BX, 4}, + {BX, 5}, + {BY, 0}, + {BY, 1}, + {BY, 2}, + {BY, 3}, + {RY, 0}, + {RY, 1}, + {RY, 2}, + {RY, 3}, + {RY, 4}, + {RY, 5}, + {RZ, 0}, + {RZ, 1}, + {RZ, 2}, + {RZ, 3}, + {RZ, 4}, + {RZ, 5}, + {D, 0}, + {D, 1}, + {D, 2}, + {D, 3}, + {D, 4}, + }, + + { + // Mode 3 (0x02) - 11 5 4 4 + {M, 0}, + {M, 1}, + {M, 2}, + {M, 3}, + {M, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {RW, 7}, + {RW, 8}, + {RW, 9}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {GW, 7}, + {GW, 8}, + {GW, 9}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BW, 7}, + {BW, 8}, + {BW, 9}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RX, 4}, + {RW, 10}, + {GY, 0}, + {GY, 1}, + {GY, 2}, + {GY, 3}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GW, 10}, + {BZ, 0}, + {GZ, 0}, + {GZ, 1}, + {GZ, 2}, + {GZ, 3}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BW, 10}, + {BZ, 1}, + {BY, 0}, + {BY, 1}, + {BY, 2}, + {BY, 3}, + {RY, 0}, + {RY, 1}, + {RY, 2}, + {RY, 3}, + {RY, 4}, + {BZ, 2}, + {RZ, 0}, + {RZ, 1}, + {RZ, 2}, + {RZ, 3}, + {RZ, 4}, + {BZ, 3}, + {D, 0}, + {D, 1}, + {D, 2}, + {D, 3}, + {D, 4}, + }, + + { + // Mode 4 (0x06) - 11 4 5 4 + {M, 0}, + {M, 1}, + {M, 2}, + {M, 3}, + {M, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {RW, 7}, + {RW, 8}, + {RW, 9}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {GW, 7}, + {GW, 8}, + {GW, 9}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BW, 7}, + {BW, 8}, + {BW, 9}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RW, 10}, + {GZ, 4}, + {GY, 0}, + {GY, 1}, + {GY, 2}, + {GY, 3}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GX, 4}, + {GW, 10}, + {GZ, 0}, + {GZ, 1}, + {GZ, 2}, + {GZ, 3}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BW, 10}, + {BZ, 1}, + {BY, 0}, + {BY, 1}, + {BY, 2}, + {BY, 3}, + {RY, 0}, + {RY, 1}, + {RY, 2}, + {RY, 3}, + {BZ, 0}, + {BZ, 2}, + {RZ, 0}, + {RZ, 1}, + {RZ, 2}, + {RZ, 3}, + {GY, 4}, + {BZ, 3}, + {D, 0}, + {D, 1}, + {D, 2}, + {D, 3}, + {D, 4}, + }, + + { + // Mode 5 (0x0a) - 11 4 4 5 + {M, 0}, + {M, 1}, + {M, 2}, + {M, 3}, + {M, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {RW, 7}, + {RW, 8}, + {RW, 9}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {GW, 7}, + {GW, 8}, + {GW, 9}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BW, 7}, + {BW, 8}, + {BW, 9}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RW, 10}, + {BY, 4}, + {GY, 0}, + {GY, 1}, + {GY, 2}, + {GY, 3}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GW, 10}, + {BZ, 0}, + {GZ, 0}, + {GZ, 1}, + {GZ, 2}, + {GZ, 3}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BX, 4}, + {BW, 10}, + {BY, 0}, + {BY, 1}, + {BY, 2}, + {BY, 3}, + {RY, 0}, + {RY, 1}, + {RY, 2}, + {RY, 3}, + {BZ, 1}, + {BZ, 2}, + {RZ, 0}, + {RZ, 1}, + {RZ, 2}, + {RZ, 3}, + {BZ, 4}, + {BZ, 3}, + {D, 0}, + {D, 1}, + {D, 2}, + {D, 3}, + {D, 4}, + }, + + { + // Mode 6 (0x0e) - 9 5 5 5 + {M, 0}, + {M, 1}, + {M, 2}, + {M, 3}, + {M, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {RW, 7}, + {RW, 8}, + {BY, 4}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {GW, 7}, + {GW, 8}, + {GY, 4}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BW, 7}, + {BW, 8}, + {BZ, 4}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RX, 4}, + {GZ, 4}, + {GY, 0}, + {GY, 1}, + {GY, 2}, + {GY, 3}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GX, 4}, + {BZ, 0}, + {GZ, 0}, + {GZ, 1}, + {GZ, 2}, + {GZ, 3}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BX, 4}, + {BZ, 1}, + {BY, 0}, + {BY, 1}, + {BY, 2}, + {BY, 3}, + {RY, 0}, + {RY, 1}, + {RY, 2}, + {RY, 3}, + {RY, 4}, + {BZ, 2}, + {RZ, 0}, + {RZ, 1}, + {RZ, 2}, + {RZ, 3}, + {RZ, 4}, + {BZ, 3}, + {D, 0}, + {D, 1}, + {D, 2}, + {D, 3}, + {D, 4}, + }, + + { + // Mode 7 (0x12) - 8 6 5 5 + {M, 0}, + {M, 1}, + {M, 2}, + {M, 3}, + {M, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {RW, 7}, + {GZ, 4}, + {BY, 4}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {GW, 7}, + {BZ, 2}, + {GY, 4}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BW, 7}, + {BZ, 3}, + {BZ, 4}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RX, 4}, + {RX, 5}, + {GY, 0}, + {GY, 1}, + {GY, 2}, + {GY, 3}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GX, 4}, + {BZ, 0}, + {GZ, 0}, + {GZ, 1}, + {GZ, 2}, + {GZ, 3}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BX, 4}, + {BZ, 1}, + {BY, 0}, + {BY, 1}, + {BY, 2}, + {BY, 3}, + {RY, 0}, + {RY, 1}, + {RY, 2}, + {RY, 3}, + {RY, 4}, + {RY, 5}, + {RZ, 0}, + {RZ, 1}, + {RZ, 2}, + {RZ, 3}, + {RZ, 4}, + {RZ, 5}, + {D, 0}, + {D, 1}, + {D, 2}, + {D, 3}, + {D, 4}, + }, + + { + // Mode 8 (0x16) - 8 5 6 5 + {M, 0}, + {M, 1}, + {M, 2}, + {M, 3}, + {M, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {RW, 7}, + {BZ, 0}, + {BY, 4}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {GW, 7}, + {GY, 5}, + {GY, 4}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BW, 7}, + {GZ, 5}, + {BZ, 4}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RX, 4}, + {GZ, 4}, + {GY, 0}, + {GY, 1}, + {GY, 2}, + {GY, 3}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GX, 4}, + {GX, 5}, + {GZ, 0}, + {GZ, 1}, + {GZ, 2}, + {GZ, 3}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BX, 4}, + {BZ, 1}, + {BY, 0}, + {BY, 1}, + {BY, 2}, + {BY, 3}, + {RY, 0}, + {RY, 1}, + {RY, 2}, + {RY, 3}, + {RY, 4}, + {BZ, 2}, + {RZ, 0}, + {RZ, 1}, + {RZ, 2}, + {RZ, 3}, + {RZ, 4}, + {BZ, 3}, + {D, 0}, + {D, 1}, + {D, 2}, + {D, 3}, + {D, 4}, + }, + + { + // Mode 9 (0x1a) - 8 5 5 6 + {M, 0}, + {M, 1}, + {M, 2}, + {M, 3}, + {M, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {RW, 7}, + {BZ, 1}, + {BY, 4}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {GW, 7}, + {BY, 5}, + {GY, 4}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BW, 7}, + {BZ, 5}, + {BZ, 4}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RX, 4}, + {GZ, 4}, + {GY, 0}, + {GY, 1}, + {GY, 2}, + {GY, 3}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GX, 4}, + {BZ, 0}, + {GZ, 0}, + {GZ, 1}, + {GZ, 2}, + {GZ, 3}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BX, 4}, + {BX, 5}, + {BY, 0}, + {BY, 1}, + {BY, 2}, + {BY, 3}, + {RY, 0}, + {RY, 1}, + {RY, 2}, + {RY, 3}, + {RY, 4}, + {BZ, 2}, + {RZ, 0}, + {RZ, 1}, + {RZ, 2}, + {RZ, 3}, + {RZ, 4}, + {BZ, 3}, + {D, 0}, + {D, 1}, + {D, 2}, + {D, 3}, + {D, 4}, + }, + + { + // Mode 10 (0x1e) - 6 6 6 6 + {M, 0}, + {M, 1}, + {M, 2}, + {M, 3}, + {M, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {GZ, 4}, + {BZ, 0}, + {BZ, 1}, + {BY, 4}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GY, 5}, + {BY, 5}, + {BZ, 2}, + {GY, 4}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {GZ, 5}, + {BZ, 3}, + {BZ, 5}, + {BZ, 4}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RX, 4}, + {RX, 5}, + {GY, 0}, + {GY, 1}, + {GY, 2}, + {GY, 3}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GX, 4}, + {GX, 5}, + {GZ, 0}, + {GZ, 1}, + {GZ, 2}, + {GZ, 3}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BX, 4}, + {BX, 5}, + {BY, 0}, + {BY, 1}, + {BY, 2}, + {BY, 3}, + {RY, 0}, + {RY, 1}, + {RY, 2}, + {RY, 3}, + {RY, 4}, + {RY, 5}, + {RZ, 0}, + {RZ, 1}, + {RZ, 2}, + {RZ, 3}, + {RZ, 4}, + {RZ, 5}, + {D, 0}, + {D, 1}, + {D, 2}, + {D, 3}, + {D, 4}, + }, + + { + // Mode 11 (0x03) - 10 10 + {M, 0}, + {M, 1}, + {M, 2}, + {M, 3}, + {M, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {RW, 7}, + {RW, 8}, + {RW, 9}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {GW, 7}, + {GW, 8}, + {GW, 9}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BW, 7}, + {BW, 8}, + {BW, 9}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RX, 4}, + {RX, 5}, + {RX, 6}, + {RX, 7}, + {RX, 8}, + {RX, 9}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GX, 4}, + {GX, 5}, + {GX, 6}, + {GX, 7}, + {GX, 8}, + {GX, 9}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BX, 4}, + {BX, 5}, + {BX, 6}, + {BX, 7}, + {BX, 8}, + {BX, 9}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + }, + + { + // Mode 12 (0x07) - 11 9 + {M, 0}, + {M, 1}, + {M, 2}, + {M, 3}, + {M, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {RW, 7}, + {RW, 8}, + {RW, 9}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {GW, 7}, + {GW, 8}, + {GW, 9}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BW, 7}, + {BW, 8}, + {BW, 9}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RX, 4}, + {RX, 5}, + {RX, 6}, + {RX, 7}, + {RX, 8}, + {RW, 10}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GX, 4}, + {GX, 5}, + {GX, 6}, + {GX, 7}, + {GX, 8}, + {GW, 10}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BX, 4}, + {BX, 5}, + {BX, 6}, + {BX, 7}, + {BX, 8}, + {BW, 10}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + }, + + { + // Mode 13 (0x0b) - 12 8 + {M, 0}, + {M, 1}, + {M, 2}, + {M, 3}, + {M, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {RW, 7}, + {RW, 8}, + {RW, 9}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {GW, 7}, + {GW, 8}, + {GW, 9}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BW, 7}, + {BW, 8}, + {BW, 9}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RX, 4}, + {RX, 5}, + {RX, 6}, + {RX, 7}, + {RW, 11}, + {RW, 10}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GX, 4}, + {GX, 5}, + {GX, 6}, + {GX, 7}, + {GW, 11}, + {GW, 10}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BX, 4}, + {BX, 5}, + {BX, 6}, + {BX, 7}, + {BW, 11}, + {BW, 10}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + }, + + { + // Mode 14 (0x0f) - 16 4 + {M, 0}, + {M, 1}, + {M, 2}, + {M, 3}, + {M, 4}, + {RW, 0}, + {RW, 1}, + {RW, 2}, + {RW, 3}, + {RW, 4}, + {RW, 5}, + {RW, 6}, + {RW, 7}, + {RW, 8}, + {RW, 9}, + {GW, 0}, + {GW, 1}, + {GW, 2}, + {GW, 3}, + {GW, 4}, + {GW, 5}, + {GW, 6}, + {GW, 7}, + {GW, 8}, + {GW, 9}, + {BW, 0}, + {BW, 1}, + {BW, 2}, + {BW, 3}, + {BW, 4}, + {BW, 5}, + {BW, 6}, + {BW, 7}, + {BW, 8}, + {BW, 9}, + {RX, 0}, + {RX, 1}, + {RX, 2}, + {RX, 3}, + {RW, 15}, + {RW, 14}, + {RW, 13}, + {RW, 12}, + {RW, 11}, + {RW, 10}, + {GX, 0}, + {GX, 1}, + {GX, 2}, + {GX, 3}, + {GW, 15}, + {GW, 14}, + {GW, 13}, + {GW, 12}, + {GW, 11}, + {GW, 10}, + {BX, 0}, + {BX, 1}, + {BX, 2}, + {BX, 3}, + {BW, 15}, + {BW, 14}, + {BW, 13}, + {BW, 12}, + {BW, 11}, + {BW, 10}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + {NA, 0}, + }, +}; + +// Mode, Partitions, Transformed, IndexPrec, RGBAPrec +const D3DX_BC6H::ModeInfo D3DX_BC6H::ms_aInfo[] = + { + {0x00, 1, true, 3, {{LDRColorA(10, 10, 10, 0), LDRColorA(5, 5, 5, 0)}, {LDRColorA(5, 5, 5, 0), LDRColorA(5, 5, 5, 0)}}}, // Mode 1 + {0x01, 1, true, 3, {{LDRColorA(7, 7, 7, 0), LDRColorA(6, 6, 6, 0)}, {LDRColorA(6, 6, 6, 0), LDRColorA(6, 6, 6, 0)}}}, // Mode 2 + {0x02, 1, true, 3, {{LDRColorA(11, 11, 11, 0), LDRColorA(5, 4, 4, 0)}, {LDRColorA(5, 4, 4, 0), LDRColorA(5, 4, 4, 0)}}}, // Mode 3 + {0x06, 1, true, 3, {{LDRColorA(11, 11, 11, 0), LDRColorA(4, 5, 4, 0)}, {LDRColorA(4, 5, 4, 0), LDRColorA(4, 5, 4, 0)}}}, // Mode 4 + {0x0a, 1, true, 3, {{LDRColorA(11, 11, 11, 0), LDRColorA(4, 4, 5, 0)}, {LDRColorA(4, 4, 5, 0), LDRColorA(4, 4, 5, 0)}}}, // Mode 5 + {0x0e, 1, true, 3, {{LDRColorA(9, 9, 9, 0), LDRColorA(5, 5, 5, 0)}, {LDRColorA(5, 5, 5, 0), LDRColorA(5, 5, 5, 0)}}}, // Mode 6 + {0x12, 1, true, 3, {{LDRColorA(8, 8, 8, 0), LDRColorA(6, 5, 5, 0)}, {LDRColorA(6, 5, 5, 0), LDRColorA(6, 5, 5, 0)}}}, // Mode 7 + {0x16, 1, true, 3, {{LDRColorA(8, 8, 8, 0), LDRColorA(5, 6, 5, 0)}, {LDRColorA(5, 6, 5, 0), LDRColorA(5, 6, 5, 0)}}}, // Mode 8 + {0x1a, 1, true, 3, {{LDRColorA(8, 8, 8, 0), LDRColorA(5, 5, 6, 0)}, {LDRColorA(5, 5, 6, 0), LDRColorA(5, 5, 6, 0)}}}, // Mode 9 + {0x1e, 1, false, 3, {{LDRColorA(6, 6, 6, 0), LDRColorA(6, 6, 6, 0)}, {LDRColorA(6, 6, 6, 0), LDRColorA(6, 6, 6, 0)}}}, // Mode 10 + {0x03, 0, false, 4, {{LDRColorA(10, 10, 10, 0), LDRColorA(10, 10, 10, 0)}, {LDRColorA(0, 0, 0, 0), LDRColorA(0, 0, 0, 0)}}}, // Mode 11 + {0x07, 0, true, 4, {{LDRColorA(11, 11, 11, 0), LDRColorA(9, 9, 9, 0)}, {LDRColorA(0, 0, 0, 0), LDRColorA(0, 0, 0, 0)}}}, // Mode 12 + {0x0b, 0, true, 4, {{LDRColorA(12, 12, 12, 0), LDRColorA(8, 8, 8, 0)}, {LDRColorA(0, 0, 0, 0), LDRColorA(0, 0, 0, 0)}}}, // Mode 13 + {0x0f, 0, true, 4, {{LDRColorA(16, 16, 16, 0), LDRColorA(4, 4, 4, 0)}, {LDRColorA(0, 0, 0, 0), LDRColorA(0, 0, 0, 0)}}}, // Mode 14 +}; + +const int D3DX_BC6H::ms_aModeToInfo[] = + { +/* 0, // Mode 1 - 0x00 + 1, // Mode 2 - 0x01 + 2, // Mode 3 - 0x02 + 10, // Mode 11 - 0x03 + -1, // Invalid - 0x04 + -1, // Invalid - 0x05 + 3, // Mode 4 - 0x06 + 11, // Mode 12 - 0x07 + -1, // Invalid - 0x08 + -1, // Invalid - 0x09 + 4, // Mode 5 - 0x0a + 12, // Mode 13 - 0x0b + -1, // Invalid - 0x0c + -1, // Invalid - 0x0d + 5, // Mode 6 - 0x0e + 13, // Mode 14 - 0x0f + -1, // Invalid - 0x10 + -1, // Invalid - 0x11 + 6, // Mode 7 - 0x12 + -1, // Reserved - 0x13 + -1, // Invalid - 0x14 + -1, // Invalid - 0x15 + 7, // Mode 8 - 0x16 + -1, // Reserved - 0x17 + -1, // Invalid - 0x18 + -1, // Invalid - 0x19 + 8, // Mode 9 - 0x1a + -1, // Reserved - 0x1b + -1, // Invalid - 0x1c + -1, // Invalid - 0x1d + 9, // Mode 10 - 0x1e + -1, // Resreved - 0x1f*/ +}; + +//------------------------------------------------------------------------------------- +// Helper functions +//------------------------------------------------------------------------------------- +BC6H_INLINE bool IsFixUpOffset(size_t uPartitions, size_t uShape, size_t uOffset) noexcept +{ + BC6H_ASSERT(uPartitions < 3 && uShape < BC6H_MAX_SHAPES && uOffset < 16); + for (size_t p = 0; p <= uPartitions; p++) + { + if (uOffset == g_aFixUp[uPartitions][uShape][p]) + { + return true; + } + } + return false; +} + +BC6H_INLINE void TransformForward(INTEndPntPair aEndPts[]) noexcept +{ + aEndPts[0].B -= aEndPts[0].A; + aEndPts[1].A -= aEndPts[0].A; + aEndPts[1].B -= aEndPts[0].A; +} + +BC6H_INLINE void TransformInverse(INTEndPntPair aEndPts[], const LDRColorA& Prec, bool bSigned) noexcept +{ + const INTColor WrapMask((1 << Prec.r) - 1, (1 << Prec.g) - 1, (1 << Prec.b) - 1); + aEndPts[0].B += aEndPts[0].A; + aEndPts[0].B &= WrapMask; + aEndPts[1].A += aEndPts[0].A; + aEndPts[1].A &= WrapMask; + aEndPts[1].B += aEndPts[0].A; + aEndPts[1].B &= WrapMask; + if (bSigned) + { + aEndPts[0].B.SignExtend(Prec); + aEndPts[1].A.SignExtend(Prec); + aEndPts[1].B.SignExtend(Prec); + } +} + +BC6H_INLINE float Norm(const INTColor& a, const INTColor& b) noexcept +{ + const float dr = float(a.r) - float(b.r); + const float dg = float(a.g) - float(b.g); + const float db = float(a.b) - float(b.b); + return dr * dr + dg * dg + db * db; +} + +// return # of bits needed to store n. handle signed or unsigned cases properly +BC6H_INLINE int NBits(int n, bool bIsSigned) noexcept +{ + int nb; + if (n == 0) + { + return 0; // no bits needed for 0, signed or not + } + else if (n > 0) + { + for (nb = 0; n; ++nb, n >>= 1) + ; + return nb + (bIsSigned ? 1 : 0); + } + else + { + BC6H_ASSERT(bIsSigned); + for (nb = 0; n < -1; ++nb, n >>= 1) + ; + return nb + 1; + } +} + +float OptimizeRGB( + const HDRColorA* const pPoints, + HDRColorA* pX, + HDRColorA* pY, + uint32_t cSteps, + size_t cPixels, + const size_t* pIndex) noexcept +{ + constexpr float fError = FLT_MAX; + const float* pC = (3 == cSteps) ? pC3 : pC4; + const float* pD = (3 == cSteps) ? pD3 : pD4; + + // Find Min and Max points, as starting point + HDRColorA X(FLT_MAX, FLT_MAX, FLT_MAX, 0.0f); + HDRColorA Y(-FLT_MAX, -FLT_MAX, -FLT_MAX, 0.0f); + + for (size_t iPoint = 0; iPoint < cPixels; iPoint++) + { + if (pPoints[pIndex[iPoint]].r < X.r) X.r = pPoints[pIndex[iPoint]].r; + if (pPoints[pIndex[iPoint]].g < X.g) X.g = pPoints[pIndex[iPoint]].g; + if (pPoints[pIndex[iPoint]].b < X.b) X.b = pPoints[pIndex[iPoint]].b; + if (pPoints[pIndex[iPoint]].r > Y.r) Y.r = pPoints[pIndex[iPoint]].r; + if (pPoints[pIndex[iPoint]].g > Y.g) Y.g = pPoints[pIndex[iPoint]].g; + if (pPoints[pIndex[iPoint]].b > Y.b) Y.b = pPoints[pIndex[iPoint]].b; + } + + // Diagonal axis + HDRColorA AB; + AB.r = Y.r - X.r; + AB.g = Y.g - X.g; + AB.b = Y.b - X.b; + + const float fAB = AB.r * AB.r + AB.g * AB.g + AB.b * AB.b; + + // Single color block.. no need to root-find + if (fAB < FLT_MIN) + { + pX->r = X.r; + pX->g = X.g; + pX->b = X.b; + pY->r = Y.r; + pY->g = Y.g; + pY->b = Y.b; + return 0.0f; + } + + // Try all four axis directions, to determine which diagonal best fits data + const float fABInv = 1.0f / fAB; + + HDRColorA Dir; + Dir.r = AB.r * fABInv; + Dir.g = AB.g * fABInv; + Dir.b = AB.b * fABInv; + + HDRColorA Mid; + Mid.r = (X.r + Y.r) * 0.5f; + Mid.g = (X.g + Y.g) * 0.5f; + Mid.b = (X.b + Y.b) * 0.5f; + + float fDir[4]; + fDir[0] = fDir[1] = fDir[2] = fDir[3] = 0.0f; + + for (size_t iPoint = 0; iPoint < cPixels; iPoint++) + { + HDRColorA Pt; + Pt.r = (pPoints[pIndex[iPoint]].r - Mid.r) * Dir.r; + Pt.g = (pPoints[pIndex[iPoint]].g - Mid.g) * Dir.g; + Pt.b = (pPoints[pIndex[iPoint]].b - Mid.b) * Dir.b; + + float f; + f = Pt.r + Pt.g + Pt.b; + fDir[0] += f * f; + f = Pt.r + Pt.g - Pt.b; + fDir[1] += f * f; + f = Pt.r - Pt.g + Pt.b; + fDir[2] += f * f; + f = Pt.r - Pt.g - Pt.b; + fDir[3] += f * f; + } + + float fDirMax = fDir[0]; + size_t iDirMax = 0; + + for (size_t iDir = 1; iDir < 4; iDir++) + { + if (fDir[iDir] > fDirMax) + { + fDirMax = fDir[iDir]; + iDirMax = iDir; + } + } + + if (iDirMax & 2) std__swap(X.g, Y.g); + if (iDirMax & 1) std__swap(X.b, Y.b); + + // Two color block.. no need to root-find + if (fAB < 1.0f / 4096.0f) + { + pX->r = X.r; + pX->g = X.g; + pX->b = X.b; + pY->r = Y.r; + pY->g = Y.g; + pY->b = Y.b; + return 0.0f; + } + + // Use Newton's Method to find local minima of sum-of-squares error. + auto const fSteps = static_cast(cSteps - 1); + + for (size_t iIteration = 0; iIteration < 8; iIteration++) + { + // Calculate new steps + HDRColorA pSteps[4] = {}; + + for (size_t iStep = 0; iStep < cSteps; iStep++) + { + pSteps[iStep].r = X.r * pC[iStep] + Y.r * pD[iStep]; + pSteps[iStep].g = X.g * pC[iStep] + Y.g * pD[iStep]; + pSteps[iStep].b = X.b * pC[iStep] + Y.b * pD[iStep]; + } + + // Calculate color direction + Dir.r = Y.r - X.r; + Dir.g = Y.g - X.g; + Dir.b = Y.b - X.b; + + const float fLen = (Dir.r * Dir.r + Dir.g * Dir.g + Dir.b * Dir.b); + + if (fLen < (1.0f / 4096.0f)) + break; + + const float fScale = fSteps / fLen; + + Dir.r *= fScale; + Dir.g *= fScale; + Dir.b *= fScale; + + // Evaluate function, and derivatives + float d2X = 0.0f, d2Y = 0.0f; + HDRColorA dX(0.0f, 0.0f, 0.0f, 0.0f), dY(0.0f, 0.0f, 0.0f, 0.0f); + + for (size_t iPoint = 0; iPoint < cPixels; iPoint++) + { + const float fDot = (pPoints[pIndex[iPoint]].r - X.r) * Dir.r + (pPoints[pIndex[iPoint]].g - X.g) * Dir.g + (pPoints[pIndex[iPoint]].b - X.b) * Dir.b; + + uint32_t iStep; + if (fDot <= 0.0f) + iStep = 0; + else if (fDot >= fSteps) + iStep = cSteps - 1; + else + iStep = uint32_t(fDot + 0.5f); + + HDRColorA Diff; + Diff.r = pSteps[iStep].r - pPoints[pIndex[iPoint]].r; + Diff.g = pSteps[iStep].g - pPoints[pIndex[iPoint]].g; + Diff.b = pSteps[iStep].b - pPoints[pIndex[iPoint]].b; + + const float fC = pC[iStep] * (1.0f / 8.0f); + const float fD = pD[iStep] * (1.0f / 8.0f); + + d2X += fC * pC[iStep]; + dX.r += fC * Diff.r; + dX.g += fC * Diff.g; + dX.b += fC * Diff.b; + + d2Y += fD * pD[iStep]; + dY.r += fD * Diff.r; + dY.g += fD * Diff.g; + dY.b += fD * Diff.b; + } + + // Move endpoints + if (d2X > 0.0f) + { + const float f = -1.0f / d2X; + + X.r += dX.r * f; + X.g += dX.g * f; + X.b += dX.b * f; + } + + if (d2Y > 0.0f) + { + const float f = -1.0f / d2Y; + + Y.r += dY.r * f; + Y.g += dY.g * f; + Y.b += dY.b * f; + } + + if ((dX.r * dX.r < fEpsilon) && (dX.g * dX.g < fEpsilon) && (dX.b * dX.b < fEpsilon) && (dY.r * dY.r < fEpsilon) && (dY.g * dY.g < fEpsilon) && (dY.b * dY.b < fEpsilon)) + { + break; + } + } + + pX->r = X.r; + pX->g = X.g; + pX->b = X.b; + pY->r = Y.r; + pY->g = Y.g; + pY->b = Y.b; + return fError; +} + +void FillWithErrorColors(HDRColorA* pOut) noexcept +{ + for (size_t i = 0; i < BC6H_NUM_PIXELS_PER_BLOCK; ++i) + { +#ifdef _DEBUG + // Use Magenta in debug as a highly-visible error color + pOut[i] = HDRColorA(1.0f, 0.0f, 1.0f, 1.0f); +#else + // In production use, default to black + pOut[i] = HDRColorA(0.0f, 0.0f, 0.0f, 1.0f); +#endif + } +} + +void D3DX_BC6H::Decode(bool bSigned, HDRColorA* pOut) const noexcept +{ + BC6H_ASSERT(pOut); + + size_t uStartBit = 0; + uint8_t uMode = GetBits(uStartBit, 2u); + if (uMode != 0x00 && uMode != 0x01) + { + uMode = static_cast((unsigned(GetBits(uStartBit, 3)) << 2) | uMode); + } + + BC6H_ASSERT(uMode < 32); + + if (ms_aModeToInfo[uMode] >= 0) + { + BC6H_ASSERT(static_cast(ms_aModeToInfo[uMode]) < std__size(ms_aInfo)); + const ModeDescriptor* desc = ms_aDesc[ms_aModeToInfo[uMode]]; + + BC6H_ASSERT(static_cast(ms_aModeToInfo[uMode]) < std__size(ms_aDesc)); + const ModeInfo& info = ms_aInfo[ms_aModeToInfo[uMode]]; + + INTEndPntPair aEndPts[BC6H_MAX_REGIONS] = {}; + uint32_t uShape = 0; + + // Read header + const size_t uHeaderBits = info.uPartitions > 0 ? 82u : 65u; + while (uStartBit < uHeaderBits) + { + const size_t uCurBit = uStartBit; + if (GetBit(uStartBit)) + { + switch (desc[uCurBit].m_eField) + { + case D: uShape |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case RW: aEndPts[0].A.r |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case RX: aEndPts[0].B.r |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case RY: aEndPts[1].A.r |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case RZ: aEndPts[1].B.r |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case GW: aEndPts[0].A.g |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case GX: aEndPts[0].B.g |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case GY: aEndPts[1].A.g |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case GZ: aEndPts[1].B.g |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case BW: aEndPts[0].A.b |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case BX: aEndPts[0].B.b |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case BY: aEndPts[1].A.b |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + case BZ: aEndPts[1].B.b |= 1 << uint32_t(desc[uCurBit].m_uBit); break; + default: { +#ifdef BC6H_LOG + BC6H_LOG("BC6H: Invalid header bits encountered during decoding\n"); +#endif + FillWithErrorColors(pOut); + return; + } + } + } + } + + BC6H_ASSERT(uShape < 64); + + // Sign extend necessary end points + if (bSigned) + { + aEndPts[0].A.SignExtend(info.RGBAPrec[0][0]); + } + if (bSigned || info.bTransformed) + { + BC6H_ASSERT(info.uPartitions < BC6H_MAX_REGIONS); + for (size_t p = 0; p <= info.uPartitions; ++p) + { + if (p != 0) + { + aEndPts[p].A.SignExtend(info.RGBAPrec[p][0]); + } + aEndPts[p].B.SignExtend(info.RGBAPrec[p][1]); + } + } + + // Inverse transform the end points + if (info.bTransformed) + { + TransformInverse(aEndPts, info.RGBAPrec[0][0], bSigned); + } + + // Read indices + for (size_t i = 0; i < BC6H_NUM_PIXELS_PER_BLOCK; ++i) + { + const size_t uNumBits = IsFixUpOffset(info.uPartitions, uShape, i) ? info.uIndexPrec - 1u : info.uIndexPrec; + if (uStartBit + uNumBits > 128) + { +#ifdef BC6H_LOG + BC6H_LOG("BC6H: Invalid block encountered during decoding\n"); +#endif + FillWithErrorColors(pOut); + return; + } + const uint8_t uIndex = GetBits(uStartBit, uNumBits); + + if (uIndex >= ((info.uPartitions > 0) ? 8 : 16)) + { +#ifdef BC6H_LOG + BC6H_LOG("BC6H: Invalid index encountered during decoding\n"); +#endif + FillWithErrorColors(pOut); + return; + } + + const size_t uRegion = g_aPartitionTable[info.uPartitions][uShape][i]; + BC6H_ASSERT(uRegion < BC6H_MAX_REGIONS); + + // Unquantize endpoints and interpolate + const int r1 = Unquantize(aEndPts[uRegion].A.r, info.RGBAPrec[0][0].r, bSigned); + const int g1 = Unquantize(aEndPts[uRegion].A.g, info.RGBAPrec[0][0].g, bSigned); + const int b1 = Unquantize(aEndPts[uRegion].A.b, info.RGBAPrec[0][0].b, bSigned); + const int r2 = Unquantize(aEndPts[uRegion].B.r, info.RGBAPrec[0][0].r, bSigned); + const int g2 = Unquantize(aEndPts[uRegion].B.g, info.RGBAPrec[0][0].g, bSigned); + const int b2 = Unquantize(aEndPts[uRegion].B.b, info.RGBAPrec[0][0].b, bSigned); + const int* aWeights = info.uPartitions > 0 ? g_aWeights3 : g_aWeights4; + INTColor fc; + fc.r = FinishUnquantize((r1 * (BC6H_WEIGHT_MAX - aWeights[uIndex]) + r2 * aWeights[uIndex] + BC6H_WEIGHT_ROUND) >> BC6H_WEIGHT_SHIFT, bSigned); + fc.g = FinishUnquantize((g1 * (BC6H_WEIGHT_MAX - aWeights[uIndex]) + g2 * aWeights[uIndex] + BC6H_WEIGHT_ROUND) >> BC6H_WEIGHT_SHIFT, bSigned); + fc.b = FinishUnquantize((b1 * (BC6H_WEIGHT_MAX - aWeights[uIndex]) + b2 * aWeights[uIndex] + BC6H_WEIGHT_ROUND) >> BC6H_WEIGHT_SHIFT, bSigned); + + HALF rgb[3]; + fc.ToF16(rgb, bSigned); + + pOut[i].r = XMConvertHalfToFloat(rgb[0]); + pOut[i].g = XMConvertHalfToFloat(rgb[1]); + pOut[i].b = XMConvertHalfToFloat(rgb[2]); + pOut[i].a = 1.0f; + } + } + else + { +#ifdef BC6H_LOG + const char* warnstr = "BC6H: Invalid mode encountered during decoding\n"; + switch (uMode) + { + case 0x13: warnstr = "BC6H: Reserved mode 10011 encountered during decoding\n"; break; + case 0x17: warnstr = "BC6H: Reserved mode 10111 encountered during decoding\n"; break; + case 0x1B: warnstr = "BC6H: Reserved mode 11011 encountered during decoding\n"; break; + case 0x1F: warnstr = "BC6H: Reserved mode 11111 encountered during decoding\n"; break; + } + BC6H_LOG(warnstr); +#endif + // Per the BC6H format spec, we must return opaque black + for (size_t i = 0; i < BC6H_NUM_PIXELS_PER_BLOCK; ++i) + { + pOut[i] = HDRColorA(0.0f, 0.0f, 0.0f, 1.0f); + } + } +} + +void D3DX_BC6H::Encode(bool bSigned, const HDRColorA* const pIn) noexcept +{ + BC6H_ASSERT(pIn); + + EncodeParams EP(pIn, bSigned); + + for (EP.uMode = 0; EP.uMode < std__size(ms_aInfo) && EP.fBestErr > 0; ++EP.uMode) + { + const uint8_t uShapes = ms_aInfo[EP.uMode].uPartitions ? 32u : 1u; + // Number of rough cases to look at. reasonable values of this are 1, uShapes/4, and uShapes + // uShapes/4 gets nearly all the cases; you can increase that a bit (say by 3 or 4) if you really want to squeeze the last bit out + const size_t uItems = std__max(1u, size_t(uShapes >> 2)); + float afRoughMSE[BC6H_MAX_SHAPES]; + uint8_t auShape[BC6H_MAX_SHAPES]; + + // pick the best uItems shapes and refine these. + for (EP.uShape = 0; EP.uShape < uShapes; ++EP.uShape) + { + size_t uShape = EP.uShape; + afRoughMSE[uShape] = RoughMSE(&EP); + auShape[uShape] = static_cast(uShape); + } + + // Bubble up the first uItems items + for (size_t i = 0; i < uItems; i++) + { + for (size_t j = i + 1; j < uShapes; j++) + { + if (afRoughMSE[i] > afRoughMSE[j]) + { + std__swap(afRoughMSE[i], afRoughMSE[j]); + std__swap(auShape[i], auShape[j]); + } + } + } + + for (size_t i = 0; i < uItems && EP.fBestErr > 0; i++) + { + EP.uShape = auShape[i]; + Refine(&EP); + } + } +} + +int D3DX_BC6H::Quantize(int iValue, int prec, bool bSigned) noexcept +{ + BC6H_ASSERT(prec > 1); // didn't bother to make it work for 1 + int q, s = 0; + if (bSigned) + { + BC6H_ASSERT(iValue >= -F16MAX && iValue <= F16MAX); + if (iValue < 0) + { + s = 1; + iValue = -iValue; + } + q = (prec >= 16) ? iValue : (iValue << (prec - 1)) / (F16MAX + 1); + if (s) + q = -q; + BC6H_ASSERT(q > -(1 << (prec - 1)) && q < (1 << (prec - 1))); + } + else + { + BC6H_ASSERT(iValue >= 0 && iValue <= F16MAX); + q = (prec >= 15) ? iValue : (iValue << prec) / (F16MAX + 1); + BC6H_ASSERT(q >= 0 && q < (1 << prec)); + } + + return q; +} + +int D3DX_BC6H::Unquantize(int comp, uint8_t uBitsPerComp, bool bSigned) noexcept +{ + int unq = 0, s = 0; + if (bSigned) + { + if (uBitsPerComp >= 16) + { + unq = comp; + } + else + { + if (comp < 0) + { + s = 1; + comp = -comp; + } + + if (comp == 0) unq = 0; + else if (comp >= ((1 << (uBitsPerComp - 1)) - 1)) + unq = 0x7FFF; + else + unq = ((comp << 15) + 0x4000) >> (uBitsPerComp - 1); + + if (s) unq = -unq; + } + } + else + { + if (uBitsPerComp >= 15) unq = comp; + else if (comp == 0) + unq = 0; + else if (comp == ((1 << uBitsPerComp) - 1)) + unq = 0xFFFF; + else + unq = ((comp << 16) + 0x8000) >> uBitsPerComp; + } + + return unq; +} + +int D3DX_BC6H::FinishUnquantize(int comp, bool bSigned) noexcept +{ + if (bSigned) + { + return (comp < 0) ? -(((-comp) * 31) >> 5) : (comp * 31) >> 5; // scale the magnitude by 31/32 + } + else + { + return (comp * 31) >> 6; // scale the magnitude by 31/64 + } +} + +bool D3DX_BC6H::EndPointsFit(const EncodeParams* pEP, const INTEndPntPair aEndPts[]) noexcept +{ + BC6H_ASSERT(pEP); + const bool bTransformed = ms_aInfo[pEP->uMode].bTransformed; + const bool bIsSigned = pEP->bSigned; + const LDRColorA& Prec0 = ms_aInfo[pEP->uMode].RGBAPrec[0][0]; + const LDRColorA& Prec1 = ms_aInfo[pEP->uMode].RGBAPrec[0][1]; + const LDRColorA& Prec2 = ms_aInfo[pEP->uMode].RGBAPrec[1][0]; + const LDRColorA& Prec3 = ms_aInfo[pEP->uMode].RGBAPrec[1][1]; + + INTColor aBits[4]; + aBits[0].r = NBits(aEndPts[0].A.r, bIsSigned); + aBits[0].g = NBits(aEndPts[0].A.g, bIsSigned); + aBits[0].b = NBits(aEndPts[0].A.b, bIsSigned); + aBits[1].r = NBits(aEndPts[0].B.r, bTransformed || bIsSigned); + aBits[1].g = NBits(aEndPts[0].B.g, bTransformed || bIsSigned); + aBits[1].b = NBits(aEndPts[0].B.b, bTransformed || bIsSigned); + if (aBits[0].r > Prec0.r || aBits[1].r > Prec1.r || aBits[0].g > Prec0.g || aBits[1].g > Prec1.g || aBits[0].b > Prec0.b || aBits[1].b > Prec1.b) + return false; + + if (ms_aInfo[pEP->uMode].uPartitions) + { + aBits[2].r = NBits(aEndPts[1].A.r, bTransformed || bIsSigned); + aBits[2].g = NBits(aEndPts[1].A.g, bTransformed || bIsSigned); + aBits[2].b = NBits(aEndPts[1].A.b, bTransformed || bIsSigned); + aBits[3].r = NBits(aEndPts[1].B.r, bTransformed || bIsSigned); + aBits[3].g = NBits(aEndPts[1].B.g, bTransformed || bIsSigned); + aBits[3].b = NBits(aEndPts[1].B.b, bTransformed || bIsSigned); + + if (aBits[2].r > Prec2.r || aBits[3].r > Prec3.r || aBits[2].g > Prec2.g || aBits[3].g > Prec3.g || aBits[2].b > Prec2.b || aBits[3].b > Prec3.b) + return false; + } + + return true; +} + +void D3DX_BC6H::GeneratePaletteQuantized(const EncodeParams* pEP, const INTEndPntPair& endPts, INTColor aPalette[]) const noexcept +{ + BC6H_ASSERT(pEP); + const size_t uIndexPrec = ms_aInfo[pEP->uMode].uIndexPrec; + const size_t uNumIndices = size_t(1) << uIndexPrec; + BC6H_ASSERT(uNumIndices > 0); + const LDRColorA& Prec = ms_aInfo[pEP->uMode].RGBAPrec[0][0]; + + // scale endpoints + INTEndPntPair unqEndPts; + unqEndPts.A.r = Unquantize(endPts.A.r, Prec.r, pEP->bSigned); + unqEndPts.A.g = Unquantize(endPts.A.g, Prec.g, pEP->bSigned); + unqEndPts.A.b = Unquantize(endPts.A.b, Prec.b, pEP->bSigned); + unqEndPts.B.r = Unquantize(endPts.B.r, Prec.r, pEP->bSigned); + unqEndPts.B.g = Unquantize(endPts.B.g, Prec.g, pEP->bSigned); + unqEndPts.B.b = Unquantize(endPts.B.b, Prec.b, pEP->bSigned); + + // interpolate + const int* aWeights = nullptr; + switch (uIndexPrec) + { + case 3: + aWeights = g_aWeights3; + BC6H_ASSERT(uNumIndices <= 8); + break; + case 4: + aWeights = g_aWeights4; + BC6H_ASSERT(uNumIndices <= 16); + break; + default: + BC6H_ASSERT(false); + for (size_t i = 0; i < uNumIndices; ++i) + { +//#pragma prefast(suppress : 22102 22103, "writing blocks in two halves confuses tool") + aPalette[i] = INTColor(0, 0, 0); + } + return; + } + + for (size_t i = 0; i < uNumIndices; ++i) + { + aPalette[i].r = FinishUnquantize( (unqEndPts.A.r * (BC6H_WEIGHT_MAX - aWeights[i]) + unqEndPts.B.r * aWeights[i] + BC6H_WEIGHT_ROUND) >> BC6H_WEIGHT_SHIFT, pEP->bSigned); + aPalette[i].g = FinishUnquantize( (unqEndPts.A.g * (BC6H_WEIGHT_MAX - aWeights[i]) + unqEndPts.B.g * aWeights[i] + BC6H_WEIGHT_ROUND) >> BC6H_WEIGHT_SHIFT, pEP->bSigned); + aPalette[i].b = FinishUnquantize( (unqEndPts.A.b * (BC6H_WEIGHT_MAX - aWeights[i]) + unqEndPts.B.b * aWeights[i] + BC6H_WEIGHT_ROUND) >> BC6H_WEIGHT_SHIFT, pEP->bSigned); + } +} + +// given a collection of colors and quantized endpoints, generate a palette, choose best entries, and return a single toterr +float D3DX_BC6H::MapColorsQuantized(const EncodeParams* pEP, const INTColor aColors[], size_t np, const INTEndPntPair& endPts) const noexcept +{ + BC6H_ASSERT(pEP); + + const uint8_t uIndexPrec = ms_aInfo[pEP->uMode].uIndexPrec; + auto const uNumIndices = static_cast(1u << uIndexPrec); + INTColor aPalette[BC6H_MAX_INDICES]; + GeneratePaletteQuantized(pEP, endPts, aPalette); + + float fTotErr = 0; + for (size_t i = 0; i < np; ++i) + { + const XMVECTOR vcolors = XMLoadSInt4(reinterpret_cast(&aColors[i])); + + // Compute ErrorMetricRGB + XMVECTOR tpal = XMLoadSInt4(reinterpret_cast(&aPalette[0])); + tpal = XMVectorSubtract(vcolors, tpal); + float fBestErr = XMVectorDot(tpal, tpal); + + for (int j = 1; j < uNumIndices && fBestErr > 0; ++j) + { + // Compute ErrorMetricRGB + tpal = XMLoadSInt4(reinterpret_cast(&aPalette[j])); + tpal = XMVectorSubtract(vcolors, tpal); + const float fErr = XMVectorDot(tpal, tpal); + if (fErr > fBestErr) break; // error increased, so we're done searching + if (fErr < fBestErr) fBestErr = fErr; + } + fTotErr += fBestErr; + } + return fTotErr; +} + +float D3DX_BC6H::PerturbOne(const EncodeParams* pEP, const INTColor aColors[], size_t np, uint8_t ch, const INTEndPntPair& oldEndPts, INTEndPntPair& newEndPts, float fOldErr, int do_b) const noexcept +{ + BC6H_ASSERT(pEP); + uint8_t uPrec; + switch (ch) + { + case 0: uPrec = ms_aInfo[pEP->uMode].RGBAPrec[0][0].r; break; + case 1: uPrec = ms_aInfo[pEP->uMode].RGBAPrec[0][0].g; break; + case 2: uPrec = ms_aInfo[pEP->uMode].RGBAPrec[0][0].b; break; + default: + BC6H_ASSERT(false); + newEndPts = oldEndPts; + return FLT_MAX; + } + INTEndPntPair tmpEndPts; + float fMinErr = fOldErr; + int beststep = 0; + + // copy real endpoints so we can perturb them + tmpEndPts = newEndPts = oldEndPts; + + // do a logarithmic search for the best error for this endpoint (which) + for (int step = 1 << (uPrec - 1); step; step >>= 1) + { + bool bImproved = false; + for (int sign = -1; sign <= 1; sign += 2) + { + if (do_b == 0) + { + tmpEndPts.A[ch] = newEndPts.A[ch] + sign * step; + if (tmpEndPts.A[ch] < 0 || tmpEndPts.A[ch] >= (1 << uPrec)) + continue; + } + else + { + tmpEndPts.B[ch] = newEndPts.B[ch] + sign * step; + if (tmpEndPts.B[ch] < 0 || tmpEndPts.B[ch] >= (1 << uPrec)) + continue; + } + + const float fErr = MapColorsQuantized(pEP, aColors, np, tmpEndPts); + + if (fErr < fMinErr) + { + bImproved = true; + fMinErr = fErr; + beststep = sign * step; + } + } + // if this was an improvement, move the endpoint and continue search from there + if (bImproved) + { + if (do_b == 0) + newEndPts.A[ch] += beststep; + else + newEndPts.B[ch] += beststep; + } + } + return fMinErr; +} + +void D3DX_BC6H::OptimizeOne(const EncodeParams* pEP, const INTColor aColors[], size_t np, float aOrgErr, const INTEndPntPair& aOrgEndPts, INTEndPntPair& aOptEndPts) const noexcept +{ + BC6H_ASSERT(pEP); + float aOptErr = aOrgErr; + aOptEndPts.A = aOrgEndPts.A; + aOptEndPts.B = aOrgEndPts.B; + + INTEndPntPair new_a, new_b; + INTEndPntPair newEndPts; + int do_b; + + // now optimize each channel separately + for (uint8_t ch = 0; ch < BC6H_NUM_CHANNELS; ++ch) + { + // figure out which endpoint when perturbed gives the most improvement and start there + // if we just alternate, we can easily end up in a local minima + const float fErr0 = PerturbOne(pEP, aColors, np, ch, aOptEndPts, new_a, aOptErr, 0); // perturb endpt A + const float fErr1 = PerturbOne(pEP, aColors, np, ch, aOptEndPts, new_b, aOptErr, 1); // perturb endpt B + + if (fErr0 < fErr1) + { + if (fErr0 >= aOptErr) continue; + aOptEndPts.A[ch] = new_a.A[ch]; + aOptErr = fErr0; + do_b = 1; // do B next + } + else + { + if (fErr1 >= aOptErr) continue; + aOptEndPts.B[ch] = new_b.B[ch]; + aOptErr = fErr1; + do_b = 0; // do A next + } + + // now alternate endpoints and keep trying until there is no improvement + for (;;) + { + const float fErr = PerturbOne(pEP, aColors, np, ch, aOptEndPts, newEndPts, aOptErr, do_b); + if (fErr >= aOptErr) + break; + if (do_b == 0) + aOptEndPts.A[ch] = newEndPts.A[ch]; + else + aOptEndPts.B[ch] = newEndPts.B[ch]; + aOptErr = fErr; + do_b = 1 - do_b; // now move the other endpoint + } + } +} + +void D3DX_BC6H::OptimizeEndPoints(const EncodeParams* pEP, const float aOrgErr[], const INTEndPntPair aOrgEndPts[], INTEndPntPair aOptEndPts[]) const noexcept +{ + BC6H_ASSERT(pEP); + const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; + BC6H_ASSERT(uPartitions < BC6H_MAX_REGIONS); + INTColor aPixels[BC6H_NUM_PIXELS_PER_BLOCK]; + + for (size_t p = 0; p <= uPartitions; ++p) + { + // collect the pixels in the region + size_t np = 0; + for (size_t i = 0; i < BC6H_NUM_PIXELS_PER_BLOCK; ++i) + { + if (g_aPartitionTable[p][pEP->uShape][i] == p) + { + aPixels[np++] = pEP->aIPixels[i]; + } + } + + OptimizeOne(pEP, aPixels, np, aOrgErr[p], aOrgEndPts[p], aOptEndPts[p]); + } +} + +// Swap endpoints as needed to ensure that the indices at fix up have a 0 high-order bit +void D3DX_BC6H::SwapIndices(const EncodeParams* pEP, INTEndPntPair aEndPts[], size_t aIndices[]) noexcept +{ + BC6H_ASSERT(pEP); + const size_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; + const size_t uNumIndices = size_t(1) << ms_aInfo[pEP->uMode].uIndexPrec; + const size_t uHighIndexBit = uNumIndices >> 1; + + BC6H_ASSERT(uPartitions < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES); + + for (size_t p = 0; p <= uPartitions; ++p) + { + const size_t i = g_aFixUp[uPartitions][pEP->uShape][p]; + BC6H_ASSERT(g_aPartitionTable[uPartitions][pEP->uShape][i] == p); + if (aIndices[i] & uHighIndexBit) + { + // high bit is set, swap the aEndPts and indices for this region + std__swap(aEndPts[p].A, aEndPts[p].B); + + for (size_t j = 0; j < BC6H_NUM_PIXELS_PER_BLOCK; ++j) + if (g_aPartitionTable[uPartitions][pEP->uShape][j] == p) + aIndices[j] = uNumIndices - 1 - aIndices[j]; + } + } +} + +// assign indices given a tile, shape, and quantized endpoints, return toterr for each region +void D3DX_BC6H::AssignIndices(const EncodeParams* pEP, const INTEndPntPair aEndPts[], size_t aIndices[], float aTotErr[]) const noexcept +{ + BC6H_ASSERT(pEP); + const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; + auto const uNumIndices = static_cast(1u << ms_aInfo[pEP->uMode].uIndexPrec); + + BC6H_ASSERT(uPartitions < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES); + + // build list of possibles + INTColor aPalette[BC6H_MAX_REGIONS][BC6H_MAX_INDICES]; + + for (size_t p = 0; p <= uPartitions; ++p) + { + GeneratePaletteQuantized(pEP, aEndPts[p], aPalette[p]); + aTotErr[p] = 0; + } + + for (size_t i = 0; i < BC6H_NUM_PIXELS_PER_BLOCK; ++i) + { + const uint8_t uRegion = g_aPartitionTable[uPartitions][pEP->uShape][i]; + BC6H_ASSERT(uRegion < BC6H_MAX_REGIONS); + float fBestErr = Norm(pEP->aIPixels[i], aPalette[uRegion][0]); + aIndices[i] = 0; + + for (uint8_t j = 1; j < uNumIndices && fBestErr > 0; ++j) + { + const float fErr = Norm(pEP->aIPixels[i], aPalette[uRegion][j]); + if (fErr > fBestErr) break; // error increased, so we're done searching + if (fErr < fBestErr) + { + fBestErr = fErr; + aIndices[i] = j; + } + } + aTotErr[uRegion] += fBestErr; + } +} + +void D3DX_BC6H::QuantizeEndPts(const EncodeParams* pEP, INTEndPntPair* aQntEndPts) const noexcept +{ + BC6H_ASSERT(pEP && aQntEndPts); + const INTEndPntPair* aUnqEndPts = pEP->aUnqEndPts[pEP->uShape]; + const LDRColorA& Prec = ms_aInfo[pEP->uMode].RGBAPrec[0][0]; + const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; + BC6H_ASSERT(uPartitions < BC6H_MAX_REGIONS); + + for (size_t p = 0; p <= uPartitions; ++p) + { + aQntEndPts[p].A.r = Quantize(aUnqEndPts[p].A.r, Prec.r, pEP->bSigned); + aQntEndPts[p].A.g = Quantize(aUnqEndPts[p].A.g, Prec.g, pEP->bSigned); + aQntEndPts[p].A.b = Quantize(aUnqEndPts[p].A.b, Prec.b, pEP->bSigned); + aQntEndPts[p].B.r = Quantize(aUnqEndPts[p].B.r, Prec.r, pEP->bSigned); + aQntEndPts[p].B.g = Quantize(aUnqEndPts[p].B.g, Prec.g, pEP->bSigned); + aQntEndPts[p].B.b = Quantize(aUnqEndPts[p].B.b, Prec.b, pEP->bSigned); + } +} + +void D3DX_BC6H::EmitBlock(const EncodeParams* pEP, const INTEndPntPair aEndPts[], const size_t aIndices[]) noexcept +{ + BC6H_ASSERT(pEP); + const uint8_t uRealMode = ms_aInfo[pEP->uMode].uMode; + const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; + const uint8_t uIndexPrec = ms_aInfo[pEP->uMode].uIndexPrec; + const size_t uHeaderBits = uPartitions > 0 ? 82u : 65u; + const ModeDescriptor* desc = ms_aDesc[pEP->uMode]; + size_t uStartBit = 0; + + while (uStartBit < uHeaderBits) + { + switch (desc[uStartBit].m_eField) + { + case M: SetBit(uStartBit, uint8_t(uRealMode >> desc[uStartBit].m_uBit) & 0x01u); break; + case D: SetBit(uStartBit, uint8_t(pEP->uShape >> desc[uStartBit].m_uBit) & 0x01u); break; + case RW: SetBit(uStartBit, uint8_t(aEndPts[0].A.r >> desc[uStartBit].m_uBit) & 0x01u); break; + case RX: SetBit(uStartBit, uint8_t(aEndPts[0].B.r >> desc[uStartBit].m_uBit) & 0x01u); break; + case RY: SetBit(uStartBit, uint8_t(aEndPts[1].A.r >> desc[uStartBit].m_uBit) & 0x01u); break; + case RZ: SetBit(uStartBit, uint8_t(aEndPts[1].B.r >> desc[uStartBit].m_uBit) & 0x01u); break; + case GW: SetBit(uStartBit, uint8_t(aEndPts[0].A.g >> desc[uStartBit].m_uBit) & 0x01u); break; + case GX: SetBit(uStartBit, uint8_t(aEndPts[0].B.g >> desc[uStartBit].m_uBit) & 0x01u); break; + case GY: SetBit(uStartBit, uint8_t(aEndPts[1].A.g >> desc[uStartBit].m_uBit) & 0x01u); break; + case GZ: SetBit(uStartBit, uint8_t(aEndPts[1].B.g >> desc[uStartBit].m_uBit) & 0x01u); break; + case BW: SetBit(uStartBit, uint8_t(aEndPts[0].A.b >> desc[uStartBit].m_uBit) & 0x01u); break; + case BX: SetBit(uStartBit, uint8_t(aEndPts[0].B.b >> desc[uStartBit].m_uBit) & 0x01u); break; + case BY: SetBit(uStartBit, uint8_t(aEndPts[1].A.b >> desc[uStartBit].m_uBit) & 0x01u); break; + case BZ: SetBit(uStartBit, uint8_t(aEndPts[1].B.b >> desc[uStartBit].m_uBit) & 0x01u); break; + default: BC6H_ASSERT(false); + } + } + + for (size_t i = 0; i < BC6H_NUM_PIXELS_PER_BLOCK; ++i) + { + if (IsFixUpOffset(ms_aInfo[pEP->uMode].uPartitions, pEP->uShape, i)) + SetBits(uStartBit, uIndexPrec - 1u, static_cast(aIndices[i])); + else + SetBits(uStartBit, uIndexPrec, static_cast(aIndices[i])); + } + BC6H_ASSERT(uStartBit == 128); +} + +void D3DX_BC6H::Refine(EncodeParams* pEP) noexcept +{ + BC6H_ASSERT(pEP); + const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; + BC6H_ASSERT(uPartitions < BC6H_MAX_REGIONS); + + const bool bTransformed = ms_aInfo[pEP->uMode].bTransformed; + float aOrgErr[BC6H_MAX_REGIONS], aOptErr[BC6H_MAX_REGIONS]; + INTEndPntPair aOrgEndPts[BC6H_MAX_REGIONS], aOptEndPts[BC6H_MAX_REGIONS]; + size_t aOrgIdx[BC6H_NUM_PIXELS_PER_BLOCK], aOptIdx[BC6H_NUM_PIXELS_PER_BLOCK]; + + QuantizeEndPts(pEP, aOrgEndPts); + AssignIndices(pEP, aOrgEndPts, aOrgIdx, aOrgErr); + SwapIndices(pEP, aOrgEndPts, aOrgIdx); + + if (bTransformed) TransformForward(aOrgEndPts); + if (EndPointsFit(pEP, aOrgEndPts)) + { + if (bTransformed) TransformInverse(aOrgEndPts, ms_aInfo[pEP->uMode].RGBAPrec[0][0], pEP->bSigned); + OptimizeEndPoints(pEP, aOrgErr, aOrgEndPts, aOptEndPts); + AssignIndices(pEP, aOptEndPts, aOptIdx, aOptErr); + SwapIndices(pEP, aOptEndPts, aOptIdx); + + float fOrgTotErr = 0.0f, fOptTotErr = 0.0f; + for (size_t p = 0; p <= uPartitions; ++p) + { + fOrgTotErr += aOrgErr[p]; + fOptTotErr += aOptErr[p]; + } + + if (bTransformed) TransformForward(aOptEndPts); + if (EndPointsFit(pEP, aOptEndPts) && fOptTotErr < fOrgTotErr && fOptTotErr < pEP->fBestErr) + { + pEP->fBestErr = fOptTotErr; + EmitBlock(pEP, aOptEndPts, aOptIdx); + } + else if (fOrgTotErr < pEP->fBestErr) + { + // either it stopped fitting when we optimized it, or there was no improvement + // so go back to the unoptimized endpoints which we know will fit + if (bTransformed) TransformForward(aOrgEndPts); + pEP->fBestErr = fOrgTotErr; + EmitBlock(pEP, aOrgEndPts, aOrgIdx); + } + } +} + +void D3DX_BC6H::GeneratePaletteUnquantized(const EncodeParams* pEP, size_t uRegion, INTColor aPalette[]) noexcept +{ + BC6H_ASSERT(pEP); + BC6H_ASSERT(uRegion < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES); + const INTEndPntPair& endPts = pEP->aUnqEndPts[pEP->uShape][uRegion]; + const uint8_t uIndexPrec = ms_aInfo[pEP->uMode].uIndexPrec; + auto const uNumIndices = static_cast(1u << uIndexPrec); + BC6H_ASSERT(uNumIndices > 0); + + const int* aWeights = nullptr; + switch (uIndexPrec) + { + case 3: + aWeights = g_aWeights3; + BC6H_ASSERT(uNumIndices <= 8); + break; + case 4: + aWeights = g_aWeights4; + BC6H_ASSERT(uNumIndices <= 16); + break; + default: + BC6H_ASSERT(false); + for (size_t i = 0; i < uNumIndices; ++i) + { +//#pragma prefast(suppress : 22102 22103, "writing blocks in two halves confuses tool") + aPalette[i] = INTColor(0, 0, 0); + } + return; + } + + for (size_t i = 0; i < uNumIndices; ++i) + { + aPalette[i].r = (endPts.A.r * (BC6H_WEIGHT_MAX - aWeights[i]) + endPts.B.r * aWeights[i] + BC6H_WEIGHT_ROUND) >> BC6H_WEIGHT_SHIFT; + aPalette[i].g = (endPts.A.g * (BC6H_WEIGHT_MAX - aWeights[i]) + endPts.B.g * aWeights[i] + BC6H_WEIGHT_ROUND) >> BC6H_WEIGHT_SHIFT; + aPalette[i].b = (endPts.A.b * (BC6H_WEIGHT_MAX - aWeights[i]) + endPts.B.b * aWeights[i] + BC6H_WEIGHT_ROUND) >> BC6H_WEIGHT_SHIFT; + } +} + +float D3DX_BC6H::MapColors(const EncodeParams* pEP, size_t uRegion, size_t np, const size_t* auIndex) const noexcept +{ + BC6H_ASSERT(pEP); + const uint8_t uIndexPrec = ms_aInfo[pEP->uMode].uIndexPrec; + auto const uNumIndices = static_cast(1u << uIndexPrec); + INTColor aPalette[BC6H_MAX_INDICES]; + GeneratePaletteUnquantized(pEP, uRegion, aPalette); + + float fTotalErr = 0.0f; + for (size_t i = 0; i < np; ++i) + { + float fBestErr = Norm(pEP->aIPixels[auIndex[i]], aPalette[0]); + for (uint8_t j = 1; j < uNumIndices && fBestErr > 0.0f; ++j) + { + const float fErr = Norm(pEP->aIPixels[auIndex[i]], aPalette[j]); + if (fErr > fBestErr) break; // error increased, so we're done searching + if (fErr < fBestErr) fBestErr = fErr; + } + fTotalErr += fBestErr; + } + + return fTotalErr; +} + +//#define BC6H_USE_AU_PIX_TABLE + +# ifdef BC6H_USE_AU_PIX_TABLE +size_t g_auPixIdx[BC6H_MAX_SHAPES][BC6H_MAX_REGIONS][BC6H_MAX_REGIONS][BC6H_NUM_PIXELS_PER_BLOCK]; +size_t g_np[BC6H_MAX_SHAPES][BC6H_MAX_REGIONS][BC6H_MAX_REGIONS]; + +struct InitTable +{ + InitTable() + { + for (size_t shape = 0; shape < BC6H_MAX_SHAPES; shape++) + { + for (size_t uPartitions = 0; uPartitions < BC6H_MAX_REGIONS; uPartitions++) + { + for (size_t p = 0; p < BC6H_MAX_REGIONS; ++p) + { + size_t np = 0; + for (size_t i = 0; i < BC6H_NUM_PIXELS_PER_BLOCK; ++i) + { + if (g_aPartitionTable[uPartitions][shape][i] == p) + { + g_auPixIdx[shape][uPartitions][p][np++] = i; + } + } + //BC6H_ASSERT(np > 0); + + g_np[shape][uPartitions][p] = np; + } + } + } + } +}; + +static InitTable init_au_pix_table; +#endif + +float D3DX_BC6H::RoughMSE(EncodeParams* pEP) const noexcept +{ + BC6H_ASSERT(pEP); + BC6H_ASSERT(pEP->uShape < BC6H_MAX_SHAPES); + + INTEndPntPair* aEndPts = pEP->aUnqEndPts[pEP->uShape]; + + const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions; + BC6H_ASSERT(uPartitions < BC6H_MAX_REGIONS); + + #ifndef BC6H_USE_AU_PIX_TABLE + size_t auPixIdx[BC6H_NUM_PIXELS_PER_BLOCK]; + #endif + + float fError = 0.0f; + for (size_t p = 0; p <= uPartitions; ++p) + { + #ifdef BC6H_USE_AU_PIX_TABLE + const size_t* auPixIdx = g_auPixIdx[pEP->uShape][uPartitions][p]; + size_t np = g_np[pEP->uShape][uPartitions][p]; + #else + size_t np = 0; + for (size_t i = 0; i < BC6H_NUM_PIXELS_PER_BLOCK; ++i) + { + if (g_aPartitionTable[uPartitions][pEP->uShape][i] == p) + { + auPixIdx[np++] = i; + } + } + #endif + + // handle simple cases + BC6H_ASSERT(np > 0); + if (np == 1) + { + aEndPts[p].A = pEP->aIPixels[auPixIdx[0]]; + aEndPts[p].B = pEP->aIPixels[auPixIdx[0]]; + continue; + } + else if (np == 2) + { + aEndPts[p].A = pEP->aIPixels[auPixIdx[0]]; + aEndPts[p].B = pEP->aIPixels[auPixIdx[1]]; + continue; + } + + HDRColorA epA, epB; + OptimizeRGB(pEP->aHDRPixels, &epA, &epB, 4, np, auPixIdx); + aEndPts[p].A.Set(epA, pEP->bSigned); + aEndPts[p].B.Set(epB, pEP->bSigned); + if (pEP->bSigned) + { + aEndPts[p].A.Clamp(-F16MAX, F16MAX); + aEndPts[p].B.Clamp(-F16MAX, F16MAX); + } + else + { + aEndPts[p].A.Clamp(0, F16MAX); + aEndPts[p].B.Clamp(0, F16MAX); + } + + fError += MapColors(pEP, p, np, auPixIdx); + } + + return fError; +} + +} + +//===================================================================================== +// Entry points +//===================================================================================== + +void DecodeBC6HU(void* pDest, const void* pSrc) noexcept +{ + static_assert(sizeof(Impl::D3DX_BC6H) == 16, "D3DX_BC6H should be 16 bytes"); + reinterpret_cast(pSrc)->Decode(false, reinterpret_cast(pDest)); +} + +void DecodeBC6HS(void* pDest, const void* pSrc) noexcept +{ + static_assert(sizeof(Impl::D3DX_BC6H) == 16, "D3DX_BC6H should be 16 bytes"); + reinterpret_cast(pSrc)->Decode(true, reinterpret_cast(pDest)); +} + +void EncodeBC6HU(void* pDest, const void* pSrc) noexcept +{ + static_assert(sizeof(Impl::D3DX_BC6H) == 16, "D3DX_BC6H should be 16 bytes"); + reinterpret_cast(pDest)->Encode(false, reinterpret_cast(pSrc)); +} + +void EncodeBC6HS(void* pDest, const void* pSrc) noexcept +{ + static_assert(sizeof(Impl::D3DX_BC6H) == 16, "D3DX_BC6H should be 16 bytes"); + reinterpret_cast(pDest)->Encode(true, reinterpret_cast(pSrc)); +} + +} + +# ifdef BC6H_ASSERT_UNDEF +# undef BC6H_ASSERT_UNDEF +# endif + +# ifdef BC6H_HALF_TO_FLOAT_UNDEF +# undef BC6H_HALF_TO_FLOAT_UNDEF +# undef BC6H_HALF_TO_FLOAT +# endif + +# ifdef BC6H_FLOAT_TO_HALF_UNDEF +# undef BC6H_FLOAT_TO_HALF_UNDEF +# undef BC6H_FLOAT_TO_HALF +# endif + +# undef BC6H_INLINE + +#endif + + + +// Some added code for JPlag to generate missing tokens + +enum TestEnum { + TestInstance +}; + +void test() { + do { + } while(false); + + try + { + throw new Exception(); + } + catch(const std::exception& e) + { + } + + goto x; + + bool* a = new bool[100]; +} \ No newline at end of file diff --git a/languages/csharp/README.md b/languages/csharp/README.md new file mode 100644 index 000000000..63e19d4f4 --- /dev/null +++ b/languages/csharp/README.md @@ -0,0 +1,68 @@ +# CSharp langauge module + +Extracts token from CSharp source using the ANTRL Grammar from the official [ANTLR repository](https://github.com/antlr/grammars-v4/tree/master/csharp) + +## Tokens + +- INVOCATION +- OBJECT_CREATION +- ARRAY_CREATION +- ASSIGNMENT +- FIELD +- CONSTANT +- LOCAL_VARIABLE +- IF +- SWITCH_BEGIN +- SWITCH_END +- CASE +- DO +- WHILE +- FOR +- FOREACH +- BREAK +- CONTINUE +- GOTO +- RETURN +- THROW +- CHECKED +- UNCHECKED +- LOCK +- USING +- TRY +- CATCH +- FINALLY +- NAMESPACE_BEGIN +- NAMESPACE_END +- USING_DIRECTIVE +- CLASS_BEGIN +- CLASS_END +- METHOD +- PROPERTY +- EVENT +- INDEXER +- OPERATOR +- CONSTRUCTOR +- DESTRUCTOR +- STRUCT_BEGIN +- STRUCT_END +- INTERFACE_BEGIN +- INTERFACE_END +- ENUM +- DELEGATE +- ATTRIBUTE +- IF_END +- UNSAFE +- FIXED +- METHOD_BEGIN +- METHOD_END +- STRUCT +- IF_BEGIN +- CLASS +- INTERFACE +- ENUM_BEGIN +- ENUM_END +- ENUMERAL +- ACCESSORS_BEGIN +- ACCESSORS_END +- ACCESSOR_BEGIN +- ACCESSOR_END \ No newline at end of file diff --git a/languages/csharp/src/main/java/de/jplag/csharp/Language.java b/languages/csharp/src/main/java/de/jplag/csharp/CSharpLanguage.java similarity index 92% rename from languages/csharp/src/main/java/de/jplag/csharp/Language.java rename to languages/csharp/src/main/java/de/jplag/csharp/CSharpLanguage.java index 7de464d13..401727bf6 100644 --- a/languages/csharp/src/main/java/de/jplag/csharp/Language.java +++ b/languages/csharp/src/main/java/de/jplag/csharp/CSharpLanguage.java @@ -14,7 +14,7 @@ * @author Timur Saglam */ @MetaInfServices(de.jplag.Language.class) -public class Language implements de.jplag.Language { +public class CSharpLanguage implements de.jplag.Language { private static final String NAME = "C# 6 Parser"; private static final String IDENTIFIER = "csharp"; private static final String[] FILE_ENDINGS = new String[] {".cs", ".CS"}; @@ -22,7 +22,7 @@ public class Language implements de.jplag.Language { private final CSharpParserAdapter parser; - public Language() { + public CSharpLanguage() { parser = new CSharpParserAdapter(); } diff --git a/languages/csharp/src/main/java/de/jplag/csharp/CSharpParserAdapter.java b/languages/csharp/src/main/java/de/jplag/csharp/CSharpParserAdapter.java index a3668b1a2..3b2b0d8a2 100644 --- a/languages/csharp/src/main/java/de/jplag/csharp/CSharpParserAdapter.java +++ b/languages/csharp/src/main/java/de/jplag/csharp/CSharpParserAdapter.java @@ -1,7 +1,7 @@ package de.jplag.csharp; +import java.io.BufferedReader; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -19,6 +19,7 @@ import de.jplag.TokenType; import de.jplag.csharp.grammar.CSharpLexer; import de.jplag.csharp.grammar.CSharpParser; +import de.jplag.util.FileUtils; /** * Parser adapter for the ANTLR 4 CSharp Parser and Lexer. It receives file to parse and passes them to the ANTLR @@ -51,11 +52,11 @@ public List parse(Set files) throws ParsingException { } private void parseFile(File file) throws ParsingException { - try (FileInputStream inputStream = new FileInputStream(file)) { + try (BufferedReader reader = FileUtils.openFileReader(file)) { currentFile = file; // create a lexer, a parser and a buffer between them. - CSharpLexer lexer = new CSharpLexer(CharStreams.fromStream(inputStream)); + CSharpLexer lexer = new CSharpLexer(CharStreams.fromReader(reader)); CommonTokenStream tokens = new CommonTokenStream(lexer); CSharpParser parser = new CSharpParser(tokens); diff --git a/languages/csharp/src/main/java/de/jplag/csharp/CSharpTokenType.java b/languages/csharp/src/main/java/de/jplag/csharp/CSharpTokenType.java index 30bf18499..f8d6a4347 100644 --- a/languages/csharp/src/main/java/de/jplag/csharp/CSharpTokenType.java +++ b/languages/csharp/src/main/java/de/jplag/csharp/CSharpTokenType.java @@ -71,6 +71,7 @@ public enum CSharpTokenType implements TokenType { private final String description; + @Override public String getDescription() { return this.description; } diff --git a/languages/csharp/src/test/java/de/jplag/csharp/MinimalCSharpTest.java b/languages/csharp/src/test/java/de/jplag/csharp/MinimalCSharpTest.java index 5f8a3135e..e4f710ab0 100644 --- a/languages/csharp/src/test/java/de/jplag/csharp/MinimalCSharpTest.java +++ b/languages/csharp/src/test/java/de/jplag/csharp/MinimalCSharpTest.java @@ -50,7 +50,7 @@ class MinimalCSharpTest { @BeforeEach public void setUp() { - language = new Language(); + language = new CSharpLanguage(); baseDirectory = BASE_PATH.toFile(); assertTrue(baseDirectory.exists(), "Could not find base directory!"); } diff --git a/languages/emf-metamodel-dynamic/README.md b/languages/emf-metamodel-dynamic/README.md index 45ef1142a..a0ff03849 100644 --- a/languages/emf-metamodel-dynamic/README.md +++ b/languages/emf-metamodel-dynamic/README.md @@ -9,7 +9,7 @@ This module is based on the EMF dependencies available on maven central. These m For the token extraction, we visit the containment tree of the metamodel and extract tokens for all metamodel elements based on their concrete metaclass. In this module, we thus extract tokens based on a dynamic token set. ### Usage -To use this module, add the `-l emf-metamodel-dynamic` flag in the CLI, or use a `JPlagOption` object with `new de.jplag.emf.dynamic.Language()` as `language` in the Java API as described in the usage information in the [readme of the main project](https://github.com/jplag/JPlag#usage) and [in the wiki](https://github.com/jplag/JPlag/wiki/1.-How-to-Use-JPlag). +To use this module, add the `-l emf-metamodel-dynamic` flag in the CLI, or use a `JPlagOption` object with `new DynamicEmfLanguage()` as `language` in the Java API as described in the usage information in the [readme of the main project](https://github.com/jplag/JPlag#usage) and [in the wiki](https://github.com/jplag/JPlag/wiki/1.-How-to-Use-JPlag). ### More Info More information can be found in the paper [*"Token-based Plagiarism Detection for Metamodels" (MODELS-C'22)*](https://dl.acm.org/doi/10.1145/3550356.3556508). diff --git a/languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/Language.java b/languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/DynamicEmfLanguage.java similarity index 64% rename from languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/Language.java rename to languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/DynamicEmfLanguage.java index 152461735..16fe53032 100644 --- a/languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/Language.java +++ b/languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/DynamicEmfLanguage.java @@ -1,25 +1,34 @@ package de.jplag.emf.dynamic; -import org.kohsuke.MetaInfServices; - +import de.jplag.emf.EmfLanguage; import de.jplag.emf.dynamic.parser.DynamicEcoreParser; +import de.jplag.emf.parser.EcoreParser; /** * Language for EMF metamodels from the Eclipse Modeling Framework (EMF). This language is based on a dynamically * created token set instead of a hand-picked one. * @author Timur Saglam */ -@MetaInfServices(de.jplag.Language.class) -public class Language extends de.jplag.emf.Language { +public class DynamicEmfLanguage extends EmfLanguage { // currently not included in the CLI private static final String NAME = "EMF metamodels (dynamically created token set)"; private static final String IDENTIFIER = "emf-dynamic"; private static final int DEFAULT_MIN_TOKEN_MATCH = 10; - public Language() { + /** + * Creates an EMF language instance with a dynamic token parser. + */ + public DynamicEmfLanguage() { super(new DynamicEcoreParser()); } + /** + * Creates an EMF language instance with a custom token parser. + */ + public DynamicEmfLanguage(EcoreParser parser) { + super(parser); + } + @Override public String getName() { return NAME; diff --git a/languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/DynamicMetamodelToken.java b/languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/DynamicMetamodelToken.java index e337baf3a..cf358cbfb 100644 --- a/languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/DynamicMetamodelToken.java +++ b/languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/DynamicMetamodelToken.java @@ -5,6 +5,7 @@ import org.eclipse.emf.ecore.EObject; +import de.jplag.TokenTrace; import de.jplag.TokenType; import de.jplag.emf.MetamodelToken; @@ -15,7 +16,7 @@ public class DynamicMetamodelToken extends MetamodelToken { public DynamicMetamodelToken(TokenType type, File file, EObject eObject) { - super(type, file, NO_VALUE, NO_VALUE, NO_VALUE, Optional.of(eObject)); + super(type, file, new TokenTrace(), Optional.of(eObject)); } public DynamicMetamodelToken(TokenType type, File file) { diff --git a/languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/DynamicMetamodelTokenType.java b/languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/DynamicMetamodelTokenType.java index 712dd9e86..27bcebf60 100644 --- a/languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/DynamicMetamodelTokenType.java +++ b/languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/DynamicMetamodelTokenType.java @@ -10,6 +10,7 @@ public DynamicMetamodelTokenType(EObject eObject) { this(eObject.eClass()); } + @Override public String getDescription() { return eClass.getName(); } diff --git a/languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/parser/DynamicEcoreParser.java b/languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/parser/DynamicEcoreParser.java index c0477eb4f..2b355ac0f 100644 --- a/languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/parser/DynamicEcoreParser.java +++ b/languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/parser/DynamicEcoreParser.java @@ -1,10 +1,12 @@ package de.jplag.emf.dynamic.parser; import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; +import de.jplag.TokenType; import de.jplag.emf.MetamodelToken; import de.jplag.emf.dynamic.DynamicMetamodelToken; -import de.jplag.emf.dynamic.DynamicMetamodelTokenType; +import de.jplag.emf.normalization.ModelSorter; import de.jplag.emf.parser.EcoreParser; import de.jplag.emf.util.AbstractMetamodelVisitor; @@ -14,12 +16,24 @@ */ public class DynamicEcoreParser extends EcoreParser { + private final DynamicElementTokenizer tokenizer; + + public DynamicEcoreParser() { + tokenizer = new DynamicElementTokenizer(); + } + @Override protected AbstractMetamodelVisitor createMetamodelVisitor() { - return new DynamicMetamodelTokenGenerator(this); + return new DynamicMetamodelTokenGenerator(this, tokenizer); } - public void addToken(DynamicMetamodelTokenType type, EObject source) { + @Override + protected void normalizeOrder(Resource modelResource) { + ModelSorter.sort(modelResource, tokenizer); + } + + @Override + public void addToken(TokenType type, EObject source) { MetamodelToken token = new DynamicMetamodelToken(type, currentFile, source); MetamodelToken metadataEnrichedToken = treeView.convertToMetadataEnrichedToken(token); tokens.add(metadataEnrichedToken); diff --git a/languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/parser/DynamicElementTokenizer.java b/languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/parser/DynamicElementTokenizer.java new file mode 100644 index 000000000..346771411 --- /dev/null +++ b/languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/parser/DynamicElementTokenizer.java @@ -0,0 +1,38 @@ +package de.jplag.emf.dynamic.parser; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EObject; + +import de.jplag.TokenType; +import de.jplag.emf.dynamic.DynamicMetamodelTokenType; +import de.jplag.emf.parser.ModelingElementTokenizer; + +/** + * Tokenizes any {@link EObject} via its {@link EClass}. Tracks all known tokens. + */ +public class DynamicElementTokenizer implements ModelingElementTokenizer { + + private final Set knownTokenTypes; + + /** + * Creates the tokenizer, initially with an empty token set. + */ + public DynamicElementTokenizer() { + knownTokenTypes = new HashSet<>(); + } + + @Override + public TokenType element2Token(EObject modelElement) { + DynamicMetamodelTokenType token = new DynamicMetamodelTokenType(modelElement); + knownTokenTypes.add(token); + return token; + } + + @Override + public Set allTokenTypes() { + return Set.copyOf(knownTokenTypes); + } +} diff --git a/languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/parser/DynamicMetamodelTokenGenerator.java b/languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/parser/DynamicMetamodelTokenGenerator.java index 718a18457..d77f17e1d 100644 --- a/languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/parser/DynamicMetamodelTokenGenerator.java +++ b/languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/parser/DynamicMetamodelTokenGenerator.java @@ -2,7 +2,6 @@ import org.eclipse.emf.ecore.EObject; -import de.jplag.emf.dynamic.DynamicMetamodelTokenType; import de.jplag.emf.util.AbstractMetamodelVisitor; /** @@ -11,19 +10,19 @@ */ public class DynamicMetamodelTokenGenerator extends AbstractMetamodelVisitor { private final DynamicEcoreParser parser; + private final DynamicElementTokenizer tokenizer; /** * Creates the visitor. * @param parser is the parser which receives the generated tokens. */ - public DynamicMetamodelTokenGenerator(DynamicEcoreParser parser) { - super(false); + public DynamicMetamodelTokenGenerator(DynamicEcoreParser parser, DynamicElementTokenizer tokenizer) { this.parser = parser; + this.tokenizer = tokenizer; } @Override protected void visitEObject(EObject eObject) { - var tokenType = new DynamicMetamodelTokenType(eObject); - parser.addToken(tokenType, eObject); + parser.addToken(tokenizer.element2Token(eObject), eObject); } } diff --git a/languages/emf-metamodel-dynamic/src/test/java/de/jplag/emf/dynamic/MinimalDynamicMetamodelTest.java b/languages/emf-metamodel-dynamic/src/test/java/de/jplag/emf/dynamic/MinimalDynamicMetamodelTest.java index a5cc19562..0911fd455 100644 --- a/languages/emf-metamodel-dynamic/src/test/java/de/jplag/emf/dynamic/MinimalDynamicMetamodelTest.java +++ b/languages/emf-metamodel-dynamic/src/test/java/de/jplag/emf/dynamic/MinimalDynamicMetamodelTest.java @@ -13,6 +13,7 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,6 +22,7 @@ import de.jplag.Token; import de.jplag.TokenPrinter; import de.jplag.TokenType; +import de.jplag.emf.EmfLanguage; import de.jplag.testutils.FileUtil; import de.jplag.testutils.TokenUtils; @@ -36,18 +38,19 @@ class MinimalDynamicMetamodelTest { @BeforeEach public void setUp() { - language = new Language(); + language = new DynamicEmfLanguage(); baseDirectory = BASE_PATH.toFile(); FileUtil.assertDirectory(baseDirectory, TEST_SUBJECTS); } @Test + @DisplayName("Test tokens generated from example metamodels") void testBookstoreMetamodels() throws ParsingException { List testFiles = Arrays.stream(TEST_SUBJECTS).map(path -> new File(BASE_PATH.toFile(), path)).toList(); List result = language.parse(new HashSet<>(testFiles)); List tokenTypes = result.stream().map(Token::getType).toList(); - logger.debug(TokenPrinter.printTokens(result, baseDirectory, Optional.of(Language.VIEW_FILE_SUFFIX))); - logger.info("parsed token types: " + tokenTypes.stream().map(TokenType::getDescription).toList().toString()); + logger.debug(TokenPrinter.printTokens(result, baseDirectory, Optional.of(EmfLanguage.VIEW_FILE_SUFFIX))); + logger.info("parsed token types: " + tokenTypes.stream().map(TokenType::getDescription).toList()); assertEquals(94, tokenTypes.size()); assertEquals(7, new HashSet<>(tokenTypes.stream().filter(DynamicMetamodelTokenType.class::isInstance).toList()).size()); @@ -62,6 +65,6 @@ void testBookstoreMetamodels() throws ParsingException { @AfterEach public void tearDown() { - FileUtil.clearFiles(new File(BASE_PATH.toString()), Language.VIEW_FILE_SUFFIX); + FileUtil.clearFiles(new File(BASE_PATH.toString()), EmfLanguage.VIEW_FILE_SUFFIX); } } diff --git a/languages/emf-metamodel/README.md b/languages/emf-metamodel/README.md index 00413202b..fc203805d 100644 --- a/languages/emf-metamodel/README.md +++ b/languages/emf-metamodel/README.md @@ -9,7 +9,7 @@ This module is based on the EMF dependencies available on maven central. These m For the token extraction, we visit the containment tree of the metamodel and extract tokens for certain metamodel elements based on their metaclass. In this module, we extract tokens based on a [handcrafted token set](https://github.com/jplag/JPlag/blob/master/languages/emf-metamodel/src/main/java/de/jplag/emf/MetamodelTokenType.java). Note that not for all concrete metaclasses tokens are extracted. `EFactory`, `EGenericType`, and `EObject` are ignored. Moreover, for some metaclasses, multiple token types are extracted. Finally, some references are also used for token extraction. ### Usage -To use this module, add the `-l emf-metamodel` flag in the CLI, or use a `JPlagOption` object with `new de.jplag.emf.Language()` as `language` in the Java API as described in the usage information in the [readme of the main project](https://github.com/jplag/JPlag#usage) and [in the wiki](https://github.com/jplag/JPlag/wiki/1.-How-to-Use-JPlag). +To use this module, add the `-l emf-metamodel` flag in the CLI, or use a `JPlagOption` object with `new EmfLanguage()` as `language` in the Java API as described in the usage information in the [readme of the main project](https://github.com/jplag/JPlag#usage) and [in the wiki](https://github.com/jplag/JPlag/wiki/1.-How-to-Use-JPlag). ### More Info More information can be found in the paper [*"Token-based Plagiarism Detection for Metamodels" (MODELS-C'22)*](https://dl.acm.org/doi/10.1145/3550356.3556508). diff --git a/languages/emf-metamodel/pom.xml b/languages/emf-metamodel/pom.xml index 0e5f502b1..8b328c38d 100644 --- a/languages/emf-metamodel/pom.xml +++ b/languages/emf-metamodel/pom.xml @@ -12,7 +12,7 @@ org.eclipse.emfatic org.eclipse.emfatic.core - 1.0.0 + ${emfatic.version} org.eclipse.emf diff --git a/languages/emf-metamodel/src/main/java/de/jplag/emf/Language.java b/languages/emf-metamodel/src/main/java/de/jplag/emf/EmfLanguage.java similarity index 91% rename from languages/emf-metamodel/src/main/java/de/jplag/emf/Language.java rename to languages/emf-metamodel/src/main/java/de/jplag/emf/EmfLanguage.java index 7e7248ca5..ba3c967ac 100644 --- a/languages/emf-metamodel/src/main/java/de/jplag/emf/Language.java +++ b/languages/emf-metamodel/src/main/java/de/jplag/emf/EmfLanguage.java @@ -16,7 +16,7 @@ * @author Timur Saglam */ @MetaInfServices(de.jplag.Language.class) -public class Language implements de.jplag.Language { +public class EmfLanguage implements de.jplag.Language { public static final String VIEW_FILE_SUFFIX = ".emfatic"; public static final String FILE_ENDING = "." + EcorePackage.eNAME; @@ -26,11 +26,11 @@ public class Language implements de.jplag.Language { protected final EcoreParser parser; - public Language() { + public EmfLanguage() { this(new EcoreParser()); } - protected Language(EcoreParser parser) { + protected EmfLanguage(EcoreParser parser) { this.parser = parser; } diff --git a/languages/emf-metamodel/src/main/java/de/jplag/emf/MetamodelToken.java b/languages/emf-metamodel/src/main/java/de/jplag/emf/MetamodelToken.java index 528fb94f1..0bc6544cf 100644 --- a/languages/emf-metamodel/src/main/java/de/jplag/emf/MetamodelToken.java +++ b/languages/emf-metamodel/src/main/java/de/jplag/emf/MetamodelToken.java @@ -6,6 +6,7 @@ import org.eclipse.emf.ecore.EObject; import de.jplag.Token; +import de.jplag.TokenTrace; import de.jplag.TokenType; /** @@ -22,8 +23,8 @@ public class MetamodelToken extends Token { * @param file is the source model file. * @param eObject is the corresponding eObject in the model from which this token was extracted. */ - public MetamodelToken(MetamodelTokenType type, File file, EObject eObject) { - this(type, file, NO_VALUE, NO_VALUE, NO_VALUE, Optional.of(eObject)); + public MetamodelToken(TokenType type, File file, EObject eObject) { + this(type, file, new TokenTrace(), Optional.of(eObject)); } /** @@ -32,20 +33,18 @@ public MetamodelToken(MetamodelTokenType type, File file, EObject eObject) { * @param file is the source model file. */ public MetamodelToken(TokenType type, File file) { - this(type, file, NO_VALUE, NO_VALUE, NO_VALUE, Optional.empty()); + this(type, file, new TokenTrace(), Optional.empty()); } /** * Creates a token with column and length information. * @param type is the token type. * @param file is the source code file. - * @param line is the line index in the source code where the token resides. Cannot be smaller than 1. - * @param column is the column index, meaning where the token starts in the line. - * @param length is the length of the token in the source code. + * @param trace is the tracing information of the token, meaning line, column, and length. * @param eObject is the corresponding eObject in the model from which this token was extracted */ - public MetamodelToken(TokenType type, File file, int line, int column, int length, Optional eObject) { - super(type, file, line, column, length); + public MetamodelToken(TokenType type, File file, TokenTrace trace, Optional eObject) { + super(type, file, trace); this.eObject = eObject; } diff --git a/languages/emf-metamodel/src/main/java/de/jplag/emf/MetamodelTokenType.java b/languages/emf-metamodel/src/main/java/de/jplag/emf/MetamodelTokenType.java index a12596ea4..c90c34571 100644 --- a/languages/emf-metamodel/src/main/java/de/jplag/emf/MetamodelTokenType.java +++ b/languages/emf-metamodel/src/main/java/de/jplag/emf/MetamodelTokenType.java @@ -16,15 +16,15 @@ public enum MetamodelTokenType implements TokenType { ENUM_END(ENUM), ENUM_LITERAL("EEnumLiteral"), OPERATION("EOperation"), - OPERATION_END(OPERATION), REFERENCE("EReference"), + REFERENCE_MULT("EReference (multi-valued)"), ATTRIBUTE("EAttribute"), PARAMETER("EParameter"), INTERFACE("EInterface"), INTERFACE_END(INTERFACE), - SUPER_TYPE("ESuperType"), ID_ATTRIBUTE("EAttribute (ID)"), CONTAINMENT("EReference (Containment)"), + CONTAINMENT_MULT("EReference (Containment, multi-valued)"), ABSTRACT_CLASS("EAbstractClass"), ABSTRACT_CLASS_END(ABSTRACT_CLASS), RETURN_TYPE("EClassifier (Return Type"), @@ -37,6 +37,7 @@ public enum MetamodelTokenType implements TokenType { private final String description; private final boolean isEndToken; + @Override public String getDescription() { return description; } diff --git a/languages/emf-metamodel/src/main/java/de/jplag/emf/normalization/ContainmentOrderNormalizer.java b/languages/emf-metamodel/src/main/java/de/jplag/emf/normalization/ContainmentOrderNormalizer.java new file mode 100644 index 000000000..f8dc57934 --- /dev/null +++ b/languages/emf-metamodel/src/main/java/de/jplag/emf/normalization/ContainmentOrderNormalizer.java @@ -0,0 +1,132 @@ +package de.jplag.emf.normalization; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.emf.ecore.EObject; + +import de.jplag.TokenType; +import de.jplag.emf.parser.ModelingElementTokenizer; + +/** + * Comparator for normalizing the order in a model tree by sorting the elements of containment references according to + * their token type and then according to the distributions of token types in their subtrees. + */ +public class ContainmentOrderNormalizer implements Comparator { + + private final List modelElementsToSort; + private final Map> paths; + private final ModelingElementTokenizer tokenizer; + private final TokenVectorGenerator tokenVectorGenerator; + + /** + * Creates the normalizing comparator. + * @param modelElementsToSort are all model elements to sort with the comparator (required for normalization process). + */ + public ContainmentOrderNormalizer(List modelElementsToSort, ModelingElementTokenizer tokenizer) { + this.modelElementsToSort = modelElementsToSort; + this.tokenizer = tokenizer; + paths = new HashMap<>(); + tokenVectorGenerator = new TokenVectorGenerator(tokenizer); + } + + @Override + public int compare(EObject first, EObject second) { + TokenType firstType = tokenizer.element2Token(first); + TokenType secondType = tokenizer.element2Token(second); + + // 0. comparison if token types are absent for one or more elements. + if (firstType == null && secondType == null) { + return 0; + } else if (firstType == null) { + return -1; + } else if (secondType == null) { + return 1; + } + + // 1. comparison by token type + int comparisonByType = firstType.toString().compareTo(secondType.toString()); + if (comparisonByType != 0) { + return comparisonByType; + } + + // 2. compare by position of the nearest neighbor path of the token distribution vectors of the elements subtrees. + List path = paths.computeIfAbsent(firstType, this::calculatePath); + return path.indexOf(first) - path.indexOf(second); + } + + private List calculatePath(List elements, EObject start, double[][] distances) { + List path = new ArrayList<>(); + Set remaining = new HashSet<>(elements); + EObject current = start; + remaining.remove(current); + path.add(current); + while (!remaining.isEmpty()) { + double shortestDistance = Double.MAX_VALUE; + EObject next = null; + for (EObject potentialNext : remaining) { + double distance = distances[elements.indexOf(current)][elements.indexOf(potentialNext)]; + if (distance < shortestDistance) { + shortestDistance = distance; + next = potentialNext; + } else if (distance == shortestDistance && modelElementsToSort.indexOf(potentialNext) < modelElementsToSort.indexOf(next)) { + next = potentialNext; // Sort according to original order if equal + } + } + current = next; + remaining.remove(current); + path.add(current); + } + return path; + } + + private List calculatePath(TokenType type) { + List elements = modelElementsToSort.stream().filter(it -> type.equals(tokenizer.element2Token(it))).toList(); + + // Generate token type distributions for the subtrees of the elements to sort: + Map> subtreeVectors = new HashMap<>(); + elements.forEach(it -> subtreeVectors.put(it, tokenVectorGenerator.generateOccurenceVector(it.eAllContents()))); + + // Calculate distance matrix: + double[][] distances = new double[elements.size()][elements.size()]; + for (int from = 0; from < distances.length; from++) { + for (int to = 0; to < distances.length; to++) { + distances[from][to] = euclideanDistance(subtreeVectors.get(elements.get(from)), subtreeVectors.get(elements.get(to))); + } + } + + // Start with element that has the most tokens in the subtree: + var max = Collections.max(elements, (first, second) -> Integer.compare(countSubtreeTokens(first), countSubtreeTokens(second))); + return calculatePath(elements, max, distances); + } + + private int countSubtreeTokens(EObject modelElement) { + int count = 0; + Iterator iterator = modelElement.eAllContents(); + while (iterator.hasNext()) { + if (tokenizer.element2Token(iterator.next()) != null) { + count++; + } + } + return count; + } + + private static double euclideanDistance(List first, List second) { + if (first.size() != second.size()) { + throw new IllegalArgumentException("Lists must have the same size"); + } + double sum = 0; + for (int i = 0; i < first.size(); i++) { + double diff = first.get(i) - second.get(i); + sum += diff * diff; + } + return Math.sqrt(sum); + } +} diff --git a/languages/emf-metamodel/src/main/java/de/jplag/emf/normalization/ModelSorter.java b/languages/emf-metamodel/src/main/java/de/jplag/emf/normalization/ModelSorter.java new file mode 100644 index 000000000..0594f77c1 --- /dev/null +++ b/languages/emf-metamodel/src/main/java/de/jplag/emf/normalization/ModelSorter.java @@ -0,0 +1,53 @@ +package de.jplag.emf.normalization; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.resource.Resource; + +import de.jplag.emf.parser.ModelingElementTokenizer; +import de.jplag.emf.util.AbstractMetamodelVisitor; + +/** + * Utility class that sorts all containment references of an EMF model or metamodel. + */ +public class ModelSorter extends AbstractMetamodelVisitor { + + private final ModelingElementTokenizer tokenizer; + + /** + * Creates a model sorter. + */ + private ModelSorter(ModelingElementTokenizer tokenizer) { + this.tokenizer = tokenizer; // private constructor to hide visitor functionality. + } + + /** + * Sorts the given model or metamodel. + * @param modelResource is the resource of the model or metamodel. + * @param tokenizer provides the tokenization rules for the sorting. + */ + public static void sort(Resource modelResource, ModelingElementTokenizer tokenizer) { + modelResource.getContents().forEach(new ModelSorter(tokenizer)::visit); + } + + @Override + protected void visitEObject(EObject eObject) { + for (EReference reference : eObject.eClass().getEAllContainments()) { + if (reference.isMany()) { + Object containment = eObject.eGet(reference); + if (containment instanceof List) { + @SuppressWarnings("unchecked") // There is no cleaner way + List containmentList = (List) containment; + List sortedContent = new ArrayList<>(containmentList); + sortedContent.sort(new ContainmentOrderNormalizer(sortedContent, tokenizer)); + containmentList.clear(); + containmentList.addAll(sortedContent); + } + } + } + } + +} diff --git a/languages/emf-metamodel/src/main/java/de/jplag/emf/normalization/TokenVectorGenerator.java b/languages/emf-metamodel/src/main/java/de/jplag/emf/normalization/TokenVectorGenerator.java new file mode 100644 index 000000000..3eb4ce5ea --- /dev/null +++ b/languages/emf-metamodel/src/main/java/de/jplag/emf/normalization/TokenVectorGenerator.java @@ -0,0 +1,58 @@ +package de.jplag.emf.normalization; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.eclipse.emf.ecore.EObject; + +import de.jplag.TokenType; +import de.jplag.emf.MetamodelTokenType; +import de.jplag.emf.parser.ModelingElementTokenizer; + +/** + * Utility class for the generation of token occurrence histograms for model subtrees. + */ +public class TokenVectorGenerator { + + private final ModelingElementTokenizer tokenizer; + + public TokenVectorGenerator(ModelingElementTokenizer tokenizer) { + this.tokenizer = tokenizer; + } + + /** + * Generate a token occurrence vector for a subtree of a model. + * @param modelElements is a visitor for the subtree. + * @return a list, where each entry represents the number of tokens in the subtree. The order is determined by + * {@link MetamodelTokenType}. + */ + public List generateOccurenceVector(Iterator modelElements) { + Map tokenTypeHistogram = new HashMap<>(); + + while (modelElements.hasNext()) { + tokenizer.element2OptionalToken(modelElements.next()).ifPresent(it -> tokenTypeHistogram.merge(it, 1, Integer::sum)); + } + List occurenceVector = new ArrayList<>(); + for (TokenType type : tokenizer.allTokenTypes()) { + occurenceVector.add(tokenTypeHistogram.getOrDefault(type, 0)); + } + return normalize(occurenceVector); + } + + public static List normalize(List vector) { + double magnitude = Math.sqrt(vector.stream().mapToInt(it -> it * it).sum()); + if (magnitude == 0) { + return Collections.nCopies(vector.size(), 0.0); + } + List normalizedVector = new ArrayList<>(); + for (int element : vector) { + double normalizedValue = element / magnitude; + normalizedVector.add(normalizedValue); + } + return normalizedVector; + } +} diff --git a/languages/emf-metamodel/src/main/java/de/jplag/emf/parser/EcoreParser.java b/languages/emf-metamodel/src/main/java/de/jplag/emf/parser/EcoreParser.java index 2f740eba3..924d3d544 100644 --- a/languages/emf-metamodel/src/main/java/de/jplag/emf/parser/EcoreParser.java +++ b/languages/emf-metamodel/src/main/java/de/jplag/emf/parser/EcoreParser.java @@ -11,21 +11,22 @@ import de.jplag.AbstractParser; import de.jplag.ParsingException; import de.jplag.Token; -import de.jplag.emf.Language; +import de.jplag.TokenType; +import de.jplag.emf.EmfLanguage; import de.jplag.emf.MetamodelToken; -import de.jplag.emf.MetamodelTokenType; +import de.jplag.emf.normalization.ModelSorter; import de.jplag.emf.util.AbstractMetamodelVisitor; +import de.jplag.emf.util.AbstractModelView; import de.jplag.emf.util.EMFUtil; import de.jplag.emf.util.EmfaticModelView; /** * Parser for EMF metamodels. - * @author Timur Saglam */ public class EcoreParser extends AbstractParser { protected List tokens; protected File currentFile; - protected EmfaticModelView treeView; + protected AbstractModelView treeView; protected AbstractMetamodelVisitor visitor; /** @@ -58,16 +59,42 @@ protected void parseModelFile(File file) throws ParsingException { if (model == null) { throw new ParsingException(file, "failed to load model"); } else { - treeView = new EmfaticModelView(file, model); + normalizeOrder(model); + treeView = createView(file, model); + visitor = createMetamodelVisitor(); for (EObject root : model.getContents()) { - visitor = createMetamodelVisitor(); visitor.visit(root); } tokens.add(Token.fileEnd(currentFile)); - treeView.writeToFile(Language.VIEW_FILE_SUFFIX); + treeView.writeToFile(getCorrespondingViewFileSuffix()); } } + /** + * @return the correct view file suffix for the model view. Can be overriden in subclasses for alternative views. + */ + protected String getCorrespondingViewFileSuffix() { + return EmfLanguage.VIEW_FILE_SUFFIX; + } + + /** + * Creates a model view. Can be overriden in subclasses for alternative views. + * @param file is the path for the view file to be created. + * @param modelResource is the resource containing the metamodel. + * @return the view implementation. + * @throws ParsingException if view could not be created due to an invalid model. + */ + protected AbstractModelView createView(File file, Resource modelResource) throws ParsingException { + return new EmfaticModelView(file, modelResource); + } + + /** + * Extension point for subclasses to employ different normalization. + */ + protected void normalizeOrder(Resource modelResource) { + ModelSorter.sort(modelResource, new MetamodelElementTokenizer()); + } + /** * Extension point for subclasses to employ different token generators. * @return a token generating metamodel visitor. @@ -81,7 +108,7 @@ protected AbstractMetamodelVisitor createMetamodelVisitor() { * @param type is the token type. * @param source is the corresponding {@link EObject} for which the token is added. */ - void addToken(MetamodelTokenType type, EObject source) { + protected void addToken(TokenType type, EObject source) { MetamodelToken token = new MetamodelToken(type, currentFile, source); tokens.add(treeView.convertToMetadataEnrichedToken(token)); } diff --git a/languages/emf-metamodel/src/main/java/de/jplag/emf/parser/MetamodelElementTokenizer.java b/languages/emf-metamodel/src/main/java/de/jplag/emf/parser/MetamodelElementTokenizer.java new file mode 100644 index 000000000..f5f7c66c1 --- /dev/null +++ b/languages/emf-metamodel/src/main/java/de/jplag/emf/parser/MetamodelElementTokenizer.java @@ -0,0 +1,114 @@ +package de.jplag.emf.parser; + +import java.util.Set; + +import org.eclipse.emf.ecore.EAnnotation; +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EDataType; +import org.eclipse.emf.ecore.EEnum; +import org.eclipse.emf.ecore.EEnumLiteral; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EOperation; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EParameter; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.ETypeParameter; +import org.eclipse.emf.ecore.util.EcoreSwitch; + +import de.jplag.TokenType; +import de.jplag.emf.MetamodelTokenType; + +/** + * Tokenizer for metamodel elements. Maps any {@link EObject} to a {@link MetamodelTokenType}. + */ +public class MetamodelElementTokenizer extends EcoreSwitch implements ModelingElementTokenizer { + + @Override + public TokenType element2Token(EObject modelElement) { + return doSwitch(modelElement); + } + + @Override + public MetamodelTokenType caseEAnnotation(EAnnotation eAnnotation) { + return MetamodelTokenType.ANNOTATION; + } + + @Override + public MetamodelTokenType caseEAttribute(EAttribute eAttribute) { + if (eAttribute.isID()) { + return MetamodelTokenType.ID_ATTRIBUTE; + } else { + return MetamodelTokenType.ATTRIBUTE; + } + } + + @Override + public MetamodelTokenType caseEClass(EClass eClass) { + if (eClass.isInterface()) { + return MetamodelTokenType.INTERFACE; + } else if (eClass.isAbstract()) { + return MetamodelTokenType.ABSTRACT_CLASS; + } else { + return MetamodelTokenType.CLASS; + } + } + + @Override + public MetamodelTokenType caseEDataType(EDataType eDataType) { + return MetamodelTokenType.DATATYPE; + } + + @Override + public MetamodelTokenType caseETypeParameter(ETypeParameter eTypeParameter) { + return MetamodelTokenType.TYPE_PARAMETER; + } + + @Override + public MetamodelTokenType caseEParameter(EParameter eParameter) { + return MetamodelTokenType.PARAMETER; + } + + @Override + public MetamodelTokenType caseEOperation(EOperation eOperation) { + return MetamodelTokenType.OPERATION; + } + + @Override + public MetamodelTokenType caseEPackage(EPackage ePackage) { + return MetamodelTokenType.PACKAGE; + } + + @Override + public MetamodelTokenType caseEEnumLiteral(EEnumLiteral eEnumLiteral) { + return MetamodelTokenType.ENUM_LITERAL; + } + + @Override + public MetamodelTokenType caseEEnum(EEnum eEnum) { + return MetamodelTokenType.ENUM; + } + + @Override + public MetamodelTokenType caseEReference(EReference eReference) { + if (eReference.isContainment()) { + if (eReference.getUpperBound() == 1) { + return MetamodelTokenType.CONTAINMENT; + } else { + return MetamodelTokenType.CONTAINMENT_MULT; + } + } else { + if (eReference.getUpperBound() == 1) { + return MetamodelTokenType.REFERENCE; + } else { + return MetamodelTokenType.REFERENCE_MULT; + } + } + } + + @Override + public Set allTokenTypes() { + return Set.of(MetamodelTokenType.values()); + } + +} diff --git a/languages/emf-metamodel/src/main/java/de/jplag/emf/parser/MetamodelTokenGenerator.java b/languages/emf-metamodel/src/main/java/de/jplag/emf/parser/MetamodelTokenGenerator.java index 95b23c90d..c038c9068 100644 --- a/languages/emf-metamodel/src/main/java/de/jplag/emf/parser/MetamodelTokenGenerator.java +++ b/languages/emf-metamodel/src/main/java/de/jplag/emf/parser/MetamodelTokenGenerator.java @@ -1,135 +1,56 @@ package de.jplag.emf.parser; -import static de.jplag.emf.MetamodelTokenType.ABSTRACT_CLASS; import static de.jplag.emf.MetamodelTokenType.ABSTRACT_CLASS_END; -import static de.jplag.emf.MetamodelTokenType.ANNOTATION; -import static de.jplag.emf.MetamodelTokenType.ATTRIBUTE; import static de.jplag.emf.MetamodelTokenType.BOUND; -import static de.jplag.emf.MetamodelTokenType.CLASS; import static de.jplag.emf.MetamodelTokenType.CLASS_END; -import static de.jplag.emf.MetamodelTokenType.CONTAINMENT; -import static de.jplag.emf.MetamodelTokenType.DATATYPE; -import static de.jplag.emf.MetamodelTokenType.ENUM; import static de.jplag.emf.MetamodelTokenType.ENUM_END; -import static de.jplag.emf.MetamodelTokenType.ENUM_LITERAL; -import static de.jplag.emf.MetamodelTokenType.ID_ATTRIBUTE; -import static de.jplag.emf.MetamodelTokenType.INTERFACE; import static de.jplag.emf.MetamodelTokenType.INTERFACE_END; -import static de.jplag.emf.MetamodelTokenType.OPERATION; -import static de.jplag.emf.MetamodelTokenType.OPERATION_END; -import static de.jplag.emf.MetamodelTokenType.PACKAGE; import static de.jplag.emf.MetamodelTokenType.PACKAGE_END; -import static de.jplag.emf.MetamodelTokenType.PARAMETER; -import static de.jplag.emf.MetamodelTokenType.REFERENCE; import static de.jplag.emf.MetamodelTokenType.RETURN_TYPE; -import static de.jplag.emf.MetamodelTokenType.SUPER_TYPE; import static de.jplag.emf.MetamodelTokenType.THROWS_DECLARATION; -import static de.jplag.emf.MetamodelTokenType.TYPE_PARAMETER; -import org.eclipse.emf.ecore.EAnnotation; -import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EClass; -import org.eclipse.emf.ecore.EDataType; import org.eclipse.emf.ecore.EEnum; -import org.eclipse.emf.ecore.EEnumLiteral; +import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EOperation; import org.eclipse.emf.ecore.EPackage; -import org.eclipse.emf.ecore.EParameter; -import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.ETypeParameter; import de.jplag.emf.util.AbstractMetamodelVisitor; /** - * Visits a metamodel containment tree and extracts the relevant token. + * Visits a metamodel containment tree and extracts the relevant token. See also {@link MetamodelElementTokenizer}. * @author Timur Saglam */ public class MetamodelTokenGenerator extends AbstractMetamodelVisitor { - private EcoreParser parser; + private final EcoreParser parser; + private final ModelingElementTokenizer tokenizer; /** * Creates the visitor. * @param parser is the parser which receives the generated tokens. */ public MetamodelTokenGenerator(EcoreParser parser) { - super(true); this.parser = parser; + tokenizer = new MetamodelElementTokenizer(); } @Override - protected void visitEAnnotation(EAnnotation eAnnotation) { - parser.addToken(ANNOTATION, eAnnotation); - } - - @Override - protected void visitEAttribute(EAttribute eAttribute) { - if (eAttribute.isID()) { - parser.addToken(ID_ATTRIBUTE, eAttribute); - } else { - parser.addToken(ATTRIBUTE, eAttribute); - } - } - - @Override - protected void visitEClass(EClass eClass) { - if (eClass.isInterface()) { - parser.addToken(INTERFACE, eClass); - } else if (eClass.isAbstract()) { - parser.addToken(ABSTRACT_CLASS, eClass); - } else { - parser.addToken(CLASS, eClass); - } - eClass.getESuperTypes().forEach(it -> parser.addToken(SUPER_TYPE, eClass)); - } - - @Override - protected void visitEDataType(EDataType eDataType) { - if (!(eDataType instanceof EEnum)) { - parser.addToken(DATATYPE, eDataType); - } - } - - @Override - protected void visitEEnum(EEnum eEnum) { - parser.addToken(ENUM, eEnum); - } - - @Override - protected void visitEEnumLiteral(EEnumLiteral eEnumLiteral) { - parser.addToken(ENUM_LITERAL, eEnumLiteral); + protected void visitEObject(EObject eObject) { + // Create begin tokens for elements that directly map to a token. + tokenizer.element2OptionalToken(eObject).ifPresent(it -> parser.addToken(it, eObject)); } @Override protected void visitEOperation(EOperation eOperation) { - parser.addToken(OPERATION, eOperation); if (eOperation.getEType() != null) { parser.addToken(RETURN_TYPE, eOperation); } eOperation.getEExceptions().forEach(it -> parser.addToken(THROWS_DECLARATION, it)); } - @Override - protected void visitEPackage(EPackage ePackage) { - parser.addToken(PACKAGE, ePackage); - } - - @Override - protected void visitEParameter(EParameter eParameter) { - parser.addToken(PARAMETER, eParameter); - } - - @Override - protected void visitEReference(EReference eReference) { - if (eReference.isContainment()) { - parser.addToken(CONTAINMENT, eReference); - } else { - parser.addToken(REFERENCE, eReference); - } - } - @Override protected void visitETypeParameter(ETypeParameter eTypeParameter) { - parser.addToken(TYPE_PARAMETER, eTypeParameter); eTypeParameter.getEBounds().forEach(it -> parser.addToken(BOUND, it)); } @@ -154,9 +75,4 @@ protected void leaveEEnum(EEnum eEnum) { parser.addToken(ENUM_END, eEnum); } - @Override - protected void leaveEOperation(EOperation eOperation) { - parser.addToken(OPERATION_END, eOperation); - } - } diff --git a/languages/emf-metamodel/src/main/java/de/jplag/emf/parser/ModelingElementTokenizer.java b/languages/emf-metamodel/src/main/java/de/jplag/emf/parser/ModelingElementTokenizer.java new file mode 100644 index 000000000..bed7e55b3 --- /dev/null +++ b/languages/emf-metamodel/src/main/java/de/jplag/emf/parser/ModelingElementTokenizer.java @@ -0,0 +1,48 @@ +package de.jplag.emf.parser; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; + +import org.eclipse.emf.ecore.EObject; + +import de.jplag.TokenType; + +/** + * Tokenizer for EMF modeling elements. Maps any {@link EObject} to a {@link TokenType}. + */ +public interface ModelingElementTokenizer { + + /** + * Returns the corresponding token type for a model element. + * @param modelElement is the model element. + * @return the token type or null if no token is extracted for that element. + */ + TokenType element2Token(EObject modelElement); + + /** + * Returns the corresponding the token types for a list of model elements. See + * {@link ModelingElementTokenizer#element2Token(EObject)}. + * @param modelElements contains the model elements. + * @return the list of corresponding token types, might contain less entries than elements. + */ + default List elements2Tokens(List modelElements) { + return modelElements.stream().map(this::element2Token).filter(Objects::nonNull).toList(); + } + + /** + * Returns the corresponding token type for a model element. See + * {@link ModelingElementTokenizer#element2Token(EObject)}. + * @param modelElement is the model element. + * @return the optional token type. + */ + default Optional element2OptionalToken(EObject modelElement) { + return Optional.ofNullable(element2Token(modelElement)); + } + + /** + * @return the set of all known token types. + */ + Set allTokenTypes(); +} diff --git a/languages/emf-metamodel/src/main/java/de/jplag/emf/util/AbstractMetamodelVisitor.java b/languages/emf-metamodel/src/main/java/de/jplag/emf/util/AbstractMetamodelVisitor.java index 2f15f4086..f957bd0dc 100644 --- a/languages/emf-metamodel/src/main/java/de/jplag/emf/util/AbstractMetamodelVisitor.java +++ b/languages/emf-metamodel/src/main/java/de/jplag/emf/util/AbstractMetamodelVisitor.java @@ -1,7 +1,5 @@ package de.jplag.emf.util; -import java.util.ArrayList; - import org.eclipse.emf.ecore.EAnnotation; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EClass; @@ -26,12 +24,6 @@ */ public abstract class AbstractMetamodelVisitor { - private final boolean sortContainmentsByType; - - protected AbstractMetamodelVisitor(boolean sortContainmentsByType) { - this.sortContainmentsByType = sortContainmentsByType; - } - private int currentTreeDepth; /** @@ -48,6 +40,7 @@ public int getCurrentTreeDepth() { * @param eObject is the EObject to visit. */ public final void visit(EObject eObject) { + visitEObject(eObject); if (eObject instanceof EPackage ePackage) { visitEPackage(ePackage); @@ -98,13 +91,8 @@ public final void visit(EObject eObject) { visitENamedElement(eNamedElement); } - var children = new ArrayList<>(eObject.eContents()); - if (sortContainmentsByType) { - children.sort((first, second) -> first.eClass().getName().compareTo(second.eClass().getName())); - } - currentTreeDepth++; - for (EObject child : children) { + for (EObject child : eObject.eContents()) { visit(child); } currentTreeDepth--; diff --git a/languages/emf-metamodel/src/main/java/de/jplag/emf/util/AbstractModelView.java b/languages/emf-metamodel/src/main/java/de/jplag/emf/util/AbstractModelView.java index e0dcbf11b..d5261bc92 100644 --- a/languages/emf-metamodel/src/main/java/de/jplag/emf/util/AbstractModelView.java +++ b/languages/emf-metamodel/src/main/java/de/jplag/emf/util/AbstractModelView.java @@ -8,22 +8,32 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import de.jplag.emf.MetamodelToken; + /** * Textual representation of a model for the depiction of matches in submissions. - * @author Timur Saglam */ -public class AbstractModelView { +public abstract class AbstractModelView { protected final File file; protected final Logger logger; protected final StringBuilder viewBuilder; - public AbstractModelView(File file) { + protected AbstractModelView(File file) { this.file = file; logger = LoggerFactory.getLogger(this.getClass()); viewBuilder = new StringBuilder(); } + /** + * Creates a token with tracing information based on an existing one without. The token information may also be used to + * build up the model view. This means a model view may be only complete after passing every token to the view to + * enrich. + * @param token is the existing token without tracing information. + * @return the enriched token, with the tracing information corresponding to this view. + */ + public abstract MetamodelToken convertToMetadataEnrichedToken(MetamodelToken token); + /** * Writes the tree view into a file. * @param suffix is the suffix of the file to be written. diff --git a/languages/emf-metamodel/src/main/java/de/jplag/emf/util/EmfaticModelView.java b/languages/emf-metamodel/src/main/java/de/jplag/emf/util/EmfaticModelView.java index c2ae5c6ae..ec2b055dc 100644 --- a/languages/emf-metamodel/src/main/java/de/jplag/emf/util/EmfaticModelView.java +++ b/languages/emf-metamodel/src/main/java/de/jplag/emf/util/EmfaticModelView.java @@ -9,12 +9,16 @@ import org.eclipse.emf.ecore.EEnumLiteral; import org.eclipse.emf.ecore.ENamedElement; import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EOperation; +import org.eclipse.emf.ecore.EParameter; import org.eclipse.emf.ecore.ETypedElement; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.util.EcoreUtil.Copier; import org.eclipse.emf.emfatic.core.generator.emfatic.Writer; +import de.jplag.ParsingException; import de.jplag.Token; +import de.jplag.TokenTrace; import de.jplag.emf.MetamodelToken; import de.jplag.emf.MetamodelTokenType; @@ -22,13 +26,14 @@ * Textual view of an EMF metamodel based on Emfatic. Emfatic code is generated for the metamodel and the model elements * are then traced to line in the code. The tracing is done via hashes as model element names and keyword detection via * regex matching. The tracing is requires, as Emfatic does not provide it itself. - * @author Timur Saglam */ public final class EmfaticModelView extends AbstractModelView { // The following regular expressions match keywords of the Emfatic syntax: + private static final String PACKAGE_REGEX = "package\\s+\\S+;"; private static final String TYPE_KEYWORD_REGEX = "(package |class |datatype |enum )"; private static final String FEATURE_KEYWORD_REGEX = "(.*attr .*|op .*|.*ref .*|.*val .*).*"; private static final String TYPE_SUFFIX_REGEX = "(;| extends| \\{)"; + private static final String LINE_SUFFIX_REGEX = ";"; private static final char CLOSING_CHAR = '}'; private static final String ANYTHING_REGEX = ".*"; @@ -37,15 +42,17 @@ public final class EmfaticModelView extends AbstractModelView { private final List hashedLines; // code for model element tracing lookup private final Map elementToLine; // maps model elements to Emfatic code line numbers - private Copier modelCopier; // Allows to trace between original and copied elements + private final Copier modelCopier; // Allows to trace between original and copied elements private int lastLineIndex; // last line given to a token + private final int rootPackageIndex; /** * Creates an Emfatic view for a metamodel. * @param file is the path for the view file to be created. * @param modelResource is the resource containing the metamodel. + * @throws ParsingException if Emfatic crashes. */ - public EmfaticModelView(File file, Resource modelResource) { + public EmfaticModelView(File file, Resource modelResource) throws ParsingException { super(file); elementToLine = new HashMap<>(); lines = generateEmfaticCode(viewBuilder, modelResource); @@ -55,6 +62,7 @@ public EmfaticModelView(File file, Resource modelResource) { Resource copiedResource = EMFUtil.copyModel(modelResource, modelCopier); replaceElementNamesWithHashes(copiedResource); hashedLines = generateEmfaticCode(new StringBuilder(), copiedResource); + rootPackageIndex = findIndexOfRootPackage(hashedLines); } /** @@ -62,6 +70,7 @@ public EmfaticModelView(File file, Resource modelResource) { * @param token is the existing token without tracing information. * @return the enriched token, with the tracing information corresponding to this view. */ + @Override public MetamodelToken convertToMetadataEnrichedToken(MetamodelToken token) { int lineIndex = calculateLineIndexOf(token); String line = lines.get(lineIndex); @@ -72,7 +81,8 @@ public MetamodelToken convertToMetadataEnrichedToken(MetamodelToken token) { lineIndex++; columnIndex += columnIndex == Token.NO_VALUE ? 0 : 1; - return new MetamodelToken(token.getType(), token.getFile(), lineIndex, columnIndex, length, token.getEObject()); + TokenTrace trace = new TokenTrace(lineIndex, columnIndex, length); + return new MetamodelToken(token.getType(), token.getFile(), trace, token.getEObject()); } /** @@ -80,7 +90,7 @@ public MetamodelToken convertToMetadataEnrichedToken(MetamodelToken token) { * elements in subsequently generated Emfatic code while avoiding name collisions. */ private final void replaceElementNamesWithHashes(Resource copiedResource) { - AbstractMetamodelVisitor renamer = new AbstractMetamodelVisitor(false) { + AbstractMetamodelVisitor renamer = new AbstractMetamodelVisitor() { @Override protected void visitENamedElement(ENamedElement eNamedElement) { eNamedElement.setName(Integer.toString(eNamedElement.hashCode())); @@ -91,14 +101,31 @@ protected void visitENamedElement(ENamedElement eNamedElement) { /** * Generates Emfatic code from a model resource and splits it into lines with a string builder. + * @throws ParsingException if the Emfatic writer fails. */ - private final List generateEmfaticCode(StringBuilder builder, Resource modelResource) { + private final List generateEmfaticCode(StringBuilder builder, Resource modelResource) throws ParsingException { Writer writer = new Writer(); - String code = writer.write(modelResource, null, null); - builder.append(code); + try { + String code = writer.write(modelResource, null, null); + builder.append(code); + } catch (Exception exception) { // Emfatic does not properly handle errors, thus throws random exceptions. + throw new ParsingException(file, "Emfatic view could not be generated!", exception); + } return builder.toString().lines().toList(); } + /** + * Calculates the index of the root package declaration, as it has unique syntax in Emfatic. + */ + private final int findIndexOfRootPackage(List lines) { + for (int index = 0; index < lines.size(); index++) { + if (lines.get(index).matches(PACKAGE_REGEX)) { + return index; + } + } + return -1; + } + /** * Calculates the line index of a metamodel token from the emfatic code. If it cannot be found, the last index is used. */ @@ -126,7 +153,7 @@ private int calculateLineIndexOf(MetamodelToken token) { */ private int findEndIndexOf(int declarationIndex) { int indentation = indentationOf(lines.get(declarationIndex)); - if (declarationIndex > 1) { // exception for top level package + if (declarationIndex > rootPackageIndex) { // exception for top level package for (int i = declarationIndex + 1; i < lines.size(); i++) { String nextLine = lines.get(i); if (nextLine.length() > indentation && CLOSING_CHAR == nextLine.charAt(indentation)) { @@ -177,7 +204,8 @@ private int findLineIndexOf(ENamedElement element) { * Checks if a line (with leading whitespace removed) contains an element based on the elements hash. */ private boolean isDeclaration(ENamedElement element, String hash, String line) { - return isStructuralFeature(element, hash, line) || isEnumLiteral(element, hash, line) || isType(hash, line); + return isStructuralFeature(element, hash, line) || isTypedElement(element, hash, line) || isEnumLiteral(element, hash, line) + || isType(hash, line); } private boolean isType(String hash, String line) { @@ -188,8 +216,12 @@ private boolean isEnumLiteral(ENamedElement element, String hash, String line) { return element instanceof EEnumLiteral && line.matches(hash + ANYTHING_REGEX); } + private boolean isTypedElement(ENamedElement element, String hash, String line) { + return element instanceof EOperation && element instanceof EParameter && line.matches(FEATURE_KEYWORD_REGEX + hash + ANYTHING_REGEX); + } + private boolean isStructuralFeature(ENamedElement element, String hash, String line) { - return element instanceof ETypedElement && line.matches(FEATURE_KEYWORD_REGEX + hash + ANYTHING_REGEX); + return element instanceof ETypedElement && line.matches(FEATURE_KEYWORD_REGEX + hash + LINE_SUFFIX_REGEX); } } diff --git a/languages/emf-metamodel/src/main/java/de/jplag/emf/util/MetamodelTreeView.java b/languages/emf-metamodel/src/main/java/de/jplag/emf/util/MetamodelTreeView.java index 36a736e01..55f3647bc 100644 --- a/languages/emf-metamodel/src/main/java/de/jplag/emf/util/MetamodelTreeView.java +++ b/languages/emf-metamodel/src/main/java/de/jplag/emf/util/MetamodelTreeView.java @@ -1,75 +1,73 @@ package de.jplag.emf.util; import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.Optional; import org.eclipse.emf.ecore.ENamedElement; import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; -import de.jplag.Token; +import de.jplag.TokenTrace; import de.jplag.emf.MetamodelToken; /** - * Simplistic tree view representation of an EMF metamodel. - * @author Timur Saglam + * Very basic tree view representation of an EMF metamodel or model. */ public class MetamodelTreeView extends AbstractModelView { - - private int lineIndex; - private int columnIndex; - - private static final String INDENTATION = " "; + private final List lines; + private final Map objectToLine; /** * Creates a tree view for a metamodel. * @param file is the path to the metamodel. */ - public MetamodelTreeView(File file) { + public MetamodelTreeView(File file, Resource modelResource) { super(file); + lines = new ArrayList<>(); + objectToLine = new HashMap<>(); + TreeViewBuilder visitor = new TreeViewBuilder(); + modelResource.getContents().forEach(visitor::visit); } /** * Adds a token to the view, thus adding the index information to the token. Returns a new token enriched with the index * metadata. * @param token is the token to add. - * @param treeDepth is the current containment tree depth, required for the indentation. */ - public MetamodelToken convertToMetadataEnrichedTokenAndAdd(MetamodelToken token, int treeDepth, String prefix) { - int length = Token.NO_VALUE; - int line = Token.NO_VALUE; - int column = Token.NO_VALUE; + @Override + public MetamodelToken convertToMetadataEnrichedToken(MetamodelToken token) { Optional optionalEObject = token.getEObject(); if (optionalEObject.isPresent()) { - EObject eObject = optionalEObject.get(); - if (prefix.isEmpty() && treeDepth > 0) { - lineIndex++; - columnIndex = 0; - viewBuilder.append(System.lineSeparator()); - } + EObject object = optionalEObject.get(); + TokenTrace trace = objectToLine.get(object); + return new MetamodelToken(token.getType(), token.getFile(), trace, optionalEObject); + } + return new MetamodelToken(token.getType(), token.getFile()); + } - String tokenText = token.getType().getDescription(); - if (eObject instanceof ENamedElement element) { - tokenText = element.getName() + " : " + tokenText; - } - length = tokenText.length(); + private final class TreeViewBuilder extends AbstractMetamodelVisitor { + private static final String INDENTATION = " "; + private static final String NAME_SEPARATOR = " : "; - if (prefix.isEmpty()) { - for (int i = 0; i < treeDepth; i++) { - viewBuilder.append(INDENTATION); - columnIndex += INDENTATION.length(); - } - viewBuilder.append(tokenText); - } else { - viewBuilder.append(prefix + tokenText); - columnIndex += prefix.length(); + @Override + protected void visitEObject(EObject eObject) { + String prefix = INDENTATION.repeat(getCurrentTreeDepth()); + String line = prefix; + if (eObject instanceof ENamedElement element) { + line += element.getName() + NAME_SEPARATOR; } + line += eObject.eClass().getName(); - line = lineIndex + 1; - column = columnIndex + 1; - - columnIndex += tokenText.length(); + lines.add(line); + viewBuilder.append(line + System.lineSeparator()); + // line and column values are one-indexed + TokenTrace trace = new TokenTrace(lines.size(), prefix.length() + 1, line.trim().length()); + objectToLine.put(eObject, trace); } - return new MetamodelToken(token.getType(), token.getFile(), line, column, length, token.getEObject()); } } diff --git a/languages/emf-metamodel/src/test/java/de/jplag/emf/AbstractEmfTest.java b/languages/emf-metamodel/src/test/java/de/jplag/emf/AbstractEmfTest.java index 0abb90def..699ee2af7 100644 --- a/languages/emf-metamodel/src/test/java/de/jplag/emf/AbstractEmfTest.java +++ b/languages/emf-metamodel/src/test/java/de/jplag/emf/AbstractEmfTest.java @@ -1,11 +1,20 @@ package de.jplag.emf; +import static org.junit.jupiter.api.Assertions.assertLinesMatch; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + import java.io.File; +import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; +import org.eclipse.emf.ecore.resource.Resource; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; +import de.jplag.emf.util.EMFUtil; import de.jplag.testutils.FileUtil; /** @@ -14,7 +23,7 @@ */ public abstract class AbstractEmfTest { - protected static final Path BASE_PATH = Path.of("src", "test", "resources", "de", "jplag", "models"); + protected static final Path BASE_PATH = Path.of("src", "test", "resources", "de", "jplag", "emf"); protected static final String[] TEST_SUBJECTS = {"bookStore.ecore", // base metamodel "bookStoreExtended.ecore", // extended version of base metamodel @@ -26,13 +35,43 @@ public abstract class AbstractEmfTest { @BeforeEach protected void setUp() { - language = new Language(); + language = new EmfLanguage(); baseDirectory = BASE_PATH.toFile(); FileUtil.assertDirectory(baseDirectory, TEST_SUBJECTS); } @AfterEach protected void tearDown() { - FileUtil.clearFiles(new File(BASE_PATH.toString()), Language.VIEW_FILE_SUFFIX); + FileUtil.clearFiles(new File(BASE_PATH.toString()), EmfLanguage.VIEW_FILE_SUFFIX); + } + + /** + * Load (meta)model from file and assert it is correctly loaded. + * @param modelFile is the file to load. + * @return the loaded resource. + */ + protected Resource loadAndVerifyModel(File modelFile) { + assertTrue(modelFile.exists()); + Resource modelResource = EMFUtil.loadModelResource(modelFile); + assertNotNull(modelResource); + return modelResource; + } + + /** + * Compares the generated view file of a meta(model) with an expected one. + * @param modelFile is the file of the meta(model). + * @param viewFileSuffix is the suffix of the view file. + * @param directoryOfExpectedViews is the name of the folder where the expected view files are located. + */ + protected void assertViewFilesMatch(File modelFile, String viewFileSuffix, String directoryOfExpectedViews) { + File viewFile = new File(modelFile.getPath() + viewFileSuffix); + File expectedViewFile = BASE_PATH.resolveSibling(Path.of(directoryOfExpectedViews, viewFile.getName())).toFile(); + assertTrue(viewFile.exists()); + assertTrue(expectedViewFile.exists()); + try { + assertLinesMatch(Files.readAllLines(expectedViewFile.toPath()), Files.readAllLines(viewFile.toPath())); + } catch (IOException exception) { + fail(exception); + } } } diff --git a/languages/emf-metamodel/src/test/java/de/jplag/emf/EmfLanguageTest.java b/languages/emf-metamodel/src/test/java/de/jplag/emf/EmfLanguageTest.java new file mode 100644 index 000000000..d3ee82d25 --- /dev/null +++ b/languages/emf-metamodel/src/test/java/de/jplag/emf/EmfLanguageTest.java @@ -0,0 +1,42 @@ +package de.jplag.emf; + +import static de.jplag.emf.MetamodelTokenType.ATTRIBUTE; +import static de.jplag.emf.MetamodelTokenType.CLASS; +import static de.jplag.emf.MetamodelTokenType.CLASS_END; +import static de.jplag.emf.MetamodelTokenType.CONTAINMENT_MULT; +import static de.jplag.emf.MetamodelTokenType.PACKAGE; +import static de.jplag.emf.MetamodelTokenType.PACKAGE_END; + +import org.junit.jupiter.api.AfterEach; + +import de.jplag.testutils.FileUtil; +import de.jplag.testutils.LanguageModuleTest; +import de.jplag.testutils.datacollector.TestDataCollector; +import de.jplag.testutils.datacollector.TestSourceIgnoredLinesCollector; + +/** + * Basic EMF test that mainly serves the purpose of checking ascending line indices for the tokens with Emfatic views. + */ +public class EmfLanguageTest extends LanguageModuleTest { + + public EmfLanguageTest() { + super(new EmfLanguage(), MetamodelTokenType.class); + } + + @Override + protected void collectTestData(TestDataCollector collector) { + collector.testAllOfType(EmfLanguage.FILE_ENDING).testContainedTokens(PACKAGE, PACKAGE_END, CLASS, CLASS_END, ATTRIBUTE, CONTAINMENT_MULT); + + } + + @Override + protected void configureIgnoredLines(TestSourceIgnoredLinesCollector collector) { + // None, does not really apply for modeling artifacts. + } + + @AfterEach + protected void tearDown() { + FileUtil.clearFiles(getTestFileLocation(), EmfLanguage.VIEW_FILE_SUFFIX); // clean up the view files. + } + +} diff --git a/languages/emf-metamodel/src/test/java/de/jplag/emf/MinimalMetamodelTest.java b/languages/emf-metamodel/src/test/java/de/jplag/emf/MinimalMetamodelTest.java index 7284803d3..28f8f5347 100644 --- a/languages/emf-metamodel/src/test/java/de/jplag/emf/MinimalMetamodelTest.java +++ b/languages/emf-metamodel/src/test/java/de/jplag/emf/MinimalMetamodelTest.java @@ -30,11 +30,11 @@ void testBookstoreMetamodels() throws ParsingException { List testFiles = Arrays.stream(TEST_SUBJECTS).map(path -> new File(BASE_PATH.toFile(), path)).toList(); List result = language.parse(new HashSet<>(testFiles)); - logger.debug(TokenPrinter.printTokens(result, baseDirectory, Optional.of(Language.VIEW_FILE_SUFFIX))); + logger.debug(TokenPrinter.printTokens(result, baseDirectory, Optional.of(EmfLanguage.VIEW_FILE_SUFFIX))); List tokenTypes = result.stream().map(Token::getType).toList(); - logger.info("Parsed token types: " + tokenTypes.stream().map(TokenType::getDescription).toList().toString()); - assertEquals(82, tokenTypes.size()); - assertEquals(13, new HashSet<>(tokenTypes).size()); + logger.info("Parsed token types: " + tokenTypes.stream().map(TokenType::getDescription).toList()); + assertEquals(80, tokenTypes.size()); + assertEquals(12, new HashSet<>(tokenTypes).size()); var originalTokens = TokenUtils.tokenTypesByFile(result, testFiles.get(0)); var renamedTokens = TokenUtils.tokenTypesByFile(result, testFiles.get(3)); diff --git a/languages/emf-metamodel/src/test/java/de/jplag/emf/util/EmfaticModelViewTest.java b/languages/emf-metamodel/src/test/java/de/jplag/emf/util/EmfaticModelViewTest.java index d6f178c00..0ddebf9d8 100644 --- a/languages/emf-metamodel/src/test/java/de/jplag/emf/util/EmfaticModelViewTest.java +++ b/languages/emf-metamodel/src/test/java/de/jplag/emf/util/EmfaticModelViewTest.java @@ -1,14 +1,6 @@ package de.jplag.emf.util; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; - import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; import java.util.Arrays; import java.util.List; @@ -17,8 +9,9 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; +import de.jplag.ParsingException; import de.jplag.emf.AbstractEmfTest; -import de.jplag.emf.Language; +import de.jplag.emf.EmfLanguage; class EmfaticModelViewTest extends AbstractEmfTest { @@ -31,26 +24,16 @@ private static List provideModelNames() { @ParameterizedTest @DisplayName("Test content of emfatic view files of example metamodels") @MethodSource("provideModelNames") - void testEmfaticViewFiles(String modelName) { + void testEmfaticViewFiles(String modelName) throws ParsingException { // Load model: File modelFile = new File(baseDirectory, modelName); - assertTrue(modelFile.exists()); - Resource modelResource = EMFUtil.loadModelResource(modelFile); - assertNotNull(modelResource); + Resource modelResource = loadAndVerifyModel(modelFile); // Generate emfatic view: EmfaticModelView view = new EmfaticModelView(modelFile, modelResource); - view.writeToFile(Language.VIEW_FILE_SUFFIX); + view.writeToFile(EmfLanguage.VIEW_FILE_SUFFIX); // Compare expected vs. actual view file: - File viewFile = new File(modelFile.getPath() + Language.VIEW_FILE_SUFFIX); - File expectedViewFile = BASE_PATH.resolveSibling(Path.of(EXPECTED_VIEW_FOLDER, viewFile.getName())).toFile(); - assertTrue(viewFile.exists()); - assertTrue(expectedViewFile.exists()); - try { - assertEquals(Files.readAllLines(expectedViewFile.toPath()), Files.readAllLines(viewFile.toPath())); - } catch (IOException exception) { - fail(exception); - } + assertViewFilesMatch(modelFile, EmfLanguage.VIEW_FILE_SUFFIX, EXPECTED_VIEW_FOLDER); } } diff --git a/languages/emf-metamodel/src/test/java/de/jplag/emf/util/MetamodelTreeViewTest.java b/languages/emf-metamodel/src/test/java/de/jplag/emf/util/MetamodelTreeViewTest.java new file mode 100644 index 000000000..9a2976974 --- /dev/null +++ b/languages/emf-metamodel/src/test/java/de/jplag/emf/util/MetamodelTreeViewTest.java @@ -0,0 +1,47 @@ +package de.jplag.emf.util; + +import java.io.File; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.emf.ecore.resource.Resource; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import de.jplag.emf.AbstractEmfTest; +import de.jplag.testutils.FileUtil; + +class MetamodelTreeViewTest extends AbstractEmfTest { + + private static final String VIEW_FILE_SUFFIX = ".treeview"; + private static final String EXPECTED_VIEW_FOLDER = "treeview"; + + private static List provideModelNames() { + return Arrays.asList(TEST_SUBJECTS); + } + + @ParameterizedTest + @DisplayName("Test content of emfatic view files of example metamodels") + @MethodSource("provideModelNames") + void testEmfaticViewFiles(String modelName) { + // Load model: + File modelFile = new File(baseDirectory, modelName); + Resource modelResource = loadAndVerifyModel(modelFile); + + // Generate emfatic view: + MetamodelTreeView view = new MetamodelTreeView(modelFile, modelResource); + view.writeToFile(VIEW_FILE_SUFFIX); + + // Compare expected vs. actual view file: + assertViewFilesMatch(modelFile, VIEW_FILE_SUFFIX, EXPECTED_VIEW_FOLDER); + } + + @AfterEach + @Override + protected void tearDown() { + FileUtil.clearFiles(new File(BASE_PATH.toString()), VIEW_FILE_SUFFIX); + } + +} diff --git a/languages/emf-metamodel/src/test/resources/de/jplag/models/bookStore.ecore b/languages/emf-metamodel/src/test/resources/de/jplag/emf/bookStore.ecore similarity index 100% rename from languages/emf-metamodel/src/test/resources/de/jplag/models/bookStore.ecore rename to languages/emf-metamodel/src/test/resources/de/jplag/emf/bookStore.ecore diff --git a/languages/emf-metamodel/src/test/resources/de/jplag/models/bookStoreExtended.ecore b/languages/emf-metamodel/src/test/resources/de/jplag/emf/bookStoreExtended.ecore similarity index 100% rename from languages/emf-metamodel/src/test/resources/de/jplag/models/bookStoreExtended.ecore rename to languages/emf-metamodel/src/test/resources/de/jplag/emf/bookStoreExtended.ecore diff --git a/languages/emf-metamodel/src/test/resources/de/jplag/models/bookStoreExtendedRefactor.ecore b/languages/emf-metamodel/src/test/resources/de/jplag/emf/bookStoreExtendedRefactor.ecore similarity index 100% rename from languages/emf-metamodel/src/test/resources/de/jplag/models/bookStoreExtendedRefactor.ecore rename to languages/emf-metamodel/src/test/resources/de/jplag/emf/bookStoreExtendedRefactor.ecore diff --git a/languages/emf-metamodel/src/test/resources/de/jplag/models/bookStoreRenamed.ecore b/languages/emf-metamodel/src/test/resources/de/jplag/emf/bookStoreRenamed.ecore similarity index 100% rename from languages/emf-metamodel/src/test/resources/de/jplag/models/bookStoreRenamed.ecore rename to languages/emf-metamodel/src/test/resources/de/jplag/emf/bookStoreRenamed.ecore diff --git a/languages/emf-metamodel/src/test/resources/de/jplag/treeview/bookStore.ecore.treeview b/languages/emf-metamodel/src/test/resources/de/jplag/treeview/bookStore.ecore.treeview new file mode 100644 index 000000000..ce6ad5331 --- /dev/null +++ b/languages/emf-metamodel/src/test/resources/de/jplag/treeview/bookStore.ecore.treeview @@ -0,0 +1,13 @@ +BookStorePackage : EPackage + BookStore : EClass + owner : EAttribute + EGenericType + location : EAttribute + EGenericType + books : EReference + EGenericType + Book : EClass + name : EAttribute + EGenericType + isbn : EAttribute + EGenericType diff --git a/languages/emf-metamodel/src/test/resources/de/jplag/treeview/bookStoreExtended.ecore.treeview b/languages/emf-metamodel/src/test/resources/de/jplag/treeview/bookStoreExtended.ecore.treeview new file mode 100644 index 000000000..4fdd2c505 --- /dev/null +++ b/languages/emf-metamodel/src/test/resources/de/jplag/treeview/bookStoreExtended.ecore.treeview @@ -0,0 +1,35 @@ +BookStorePackage : EPackage + store : EPackage + BookStore : EClass + owner : EReference + EGenericType + name : EAttribute + EGenericType + location : EAttribute + EGenericType + books : EReference + EGenericType + Book : EClass + name : EAttribute + EGenericType + isbn : EAttribute + EGenericType + author : EReference + EGenericType + genre : EAttribute + EGenericType + Genre : EEnum + NOVEL : EEnumLiteral + COOKBOOK : EEnumLiteral + BIOGRAPHY : EEnumLiteral + TEXTBOOK : EEnumLiteral + person : EPackage + Author : EClass + isStageName : EAttribute + EGenericType + EGenericType + Person : EClass + firstName : EAttribute + EGenericType + lastName : EAttribute + EGenericType diff --git a/languages/emf-metamodel/src/test/resources/de/jplag/treeview/bookStoreExtendedRefactor.ecore.treeview b/languages/emf-metamodel/src/test/resources/de/jplag/treeview/bookStoreExtendedRefactor.ecore.treeview new file mode 100644 index 000000000..ca127fe5a --- /dev/null +++ b/languages/emf-metamodel/src/test/resources/de/jplag/treeview/bookStoreExtendedRefactor.ecore.treeview @@ -0,0 +1,29 @@ +BookStorePackage : EPackage + store : EPackage + Store : EClass + owner : EReference + EGenericType + name : EAttribute + EGenericType + location : EAttribute + EGenericType + BookStore : EClass + books : EReference + EGenericType + EGenericType + Book : EClass + title : EAttribute + EGenericType + isbn : EAttribute + EGenericType + author : EReference + EGenericType + category : EAttribute + EGenericType + Person : EClass + firstName : EAttribute + EGenericType + lastName : EAttribute + EGenericType + isStageName : EAttribute + EGenericType diff --git a/languages/emf-metamodel/src/test/resources/de/jplag/treeview/bookStoreRenamed.ecore.treeview b/languages/emf-metamodel/src/test/resources/de/jplag/treeview/bookStoreRenamed.ecore.treeview new file mode 100644 index 000000000..4ee5941e3 --- /dev/null +++ b/languages/emf-metamodel/src/test/resources/de/jplag/treeview/bookStoreRenamed.ecore.treeview @@ -0,0 +1,13 @@ +BookStorePackage : EPackage + Store : EClass + nameOfOwner : EAttribute + EGenericType + city : EAttribute + EGenericType + soldItems : EReference + EGenericType + Item : EClass + title : EAttribute + EGenericType + identifier : EAttribute + EGenericType diff --git a/languages/emf-model/pom.xml b/languages/emf-model/pom.xml new file mode 100644 index 000000000..763a528c0 --- /dev/null +++ b/languages/emf-model/pom.xml @@ -0,0 +1,40 @@ + + + 4.0.0 + + de.jplag + languages + ${revision} + + emf-model + + + + de.jplag + emf-metamodel-dynamic + ${revision} + + + de.jplag + language-testutils + ${revision} + test-jar + test + + + org.eclipse.emf + org.eclipse.emf.ecore + ${emf.version} + + + org.eclipse.emf + org.eclipse.emf.common + ${emf.ecore.version} + + + org.eclipse.emf + org.eclipse.emf.ecore.xmi + ${emf.ecore.xmi.version} + + + diff --git a/languages/emf-model/src/main/java/de/jplag/emf/model/EmfModelLanguage.java b/languages/emf-model/src/main/java/de/jplag/emf/model/EmfModelLanguage.java new file mode 100644 index 000000000..36f328e67 --- /dev/null +++ b/languages/emf-model/src/main/java/de/jplag/emf/model/EmfModelLanguage.java @@ -0,0 +1,59 @@ +package de.jplag.emf.model; + +import java.io.File; +import java.util.Comparator; +import java.util.List; + +import org.kohsuke.MetaInfServices; + +import de.jplag.emf.dynamic.DynamicEmfLanguage; +import de.jplag.emf.model.parser.DynamicModelParser; + +/** + * Language for EMF metamodels from the Eclipse Modeling Framework (EMF). This language is based on a dynamically + * created token set. + * @author Timur Saglam + */ +@MetaInfServices(de.jplag.Language.class) +public class EmfModelLanguage extends DynamicEmfLanguage { + private static final String NAME = "EMF models (dynamically created token set)"; + private static final String IDENTIFIER = "emf-model"; + + public static final String VIEW_FILE_SUFFIX = ".treeview"; + + public EmfModelLanguage() { + super(new DynamicModelParser()); + } + + @Override + public String[] suffixes() { + return new String[] {}; + } + + @Override + public String getName() { + return NAME; + } + + @Override + public String getIdentifier() { + return IDENTIFIER; + } + + @Override + public String viewFileSuffix() { + return VIEW_FILE_SUFFIX; + } + + @Override + public boolean expectsSubmissionOrder() { + return true; + } + + @Override + public List customizeSubmissionOrder(List sub) { + Comparator fileEndingComparator = (first, second) -> Boolean.compare(second.getName().endsWith(FILE_ENDING), + first.getName().endsWith(FILE_ENDING)); + return sub.stream().sorted(fileEndingComparator).toList(); + } +} diff --git a/languages/emf-model/src/main/java/de/jplag/emf/model/parser/DynamicModelParser.java b/languages/emf-model/src/main/java/de/jplag/emf/model/parser/DynamicModelParser.java new file mode 100644 index 000000000..70d77e55e --- /dev/null +++ b/languages/emf-model/src/main/java/de/jplag/emf/model/parser/DynamicModelParser.java @@ -0,0 +1,79 @@ +package de.jplag.emf.model.parser; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.resource.Resource; + +import de.jplag.ParsingException; +import de.jplag.emf.EmfLanguage; +import de.jplag.emf.dynamic.parser.DynamicEcoreParser; +import de.jplag.emf.model.EmfModelLanguage; +import de.jplag.emf.util.AbstractModelView; +import de.jplag.emf.util.EMFUtil; +import de.jplag.emf.util.MetamodelTreeView; + +/** + * Parser for EMF metamodels based on dynamically created tokens. + */ +public class DynamicModelParser extends DynamicEcoreParser { + private static final String VIEW_FILE_WARNING = "Skipping view file {} as submission!"; + private static final String METAPACKAGE_WARNING = "Loading model instance {} without any metamodel!"; + private static final String METAPACKAGE_ERROR = "Error, not a metapackage: "; + private static final String METAMODEL_LOADING_ERROR = "Could not load metamodel file!"; + + private static final List metapackages = new ArrayList<>(); + private static final String ALL_EXTENSIONS = "*"; + + /** + * Creates the parser. + */ + public DynamicModelParser() { + EMFUtil.registerModelExtension(ALL_EXTENSIONS); + } + + @Override + protected void parseModelFile(File file) throws ParsingException { + // implicit assumption: Metamodel gets parsed first! + if (file.getName().endsWith(EmfLanguage.FILE_ENDING)) { + parseMetamodelFile(file); + } else if (file.getName().endsWith(EmfModelLanguage.VIEW_FILE_SUFFIX)) { + logger.warn(VIEW_FILE_WARNING, file.getName()); + } else { + if (metapackages.isEmpty()) { + logger.warn(METAPACKAGE_WARNING, file.getName()); + } + super.parseModelFile(file); + } + } + + @Override + protected String getCorrespondingViewFileSuffix() { + return EmfModelLanguage.VIEW_FILE_SUFFIX; + } + + @Override + protected AbstractModelView createView(File file, Resource modelResource) { + return new MetamodelTreeView(file, modelResource); + } + + private void parseMetamodelFile(File file) throws ParsingException { + metapackages.clear(); + Resource modelResource = EMFUtil.loadModelResource(file); + if (modelResource == null) { + throw new ParsingException(file, METAMODEL_LOADING_ERROR); + } else { + for (EObject object : modelResource.getContents()) { + if (object instanceof EPackage ePackage) { + metapackages.add(ePackage); + } else { + logger.error(METAPACKAGE_ERROR, object); + } + } + EMFUtil.registerEPackageURIs(metapackages); + } + } +} diff --git a/languages/emf-model/src/test/java/de/jplag/emf/model/BookStoreFactory.java b/languages/emf-model/src/test/java/de/jplag/emf/model/BookStoreFactory.java new file mode 100644 index 000000000..5f755defa --- /dev/null +++ b/languages/emf-model/src/test/java/de/jplag/emf/model/BookStoreFactory.java @@ -0,0 +1,120 @@ +package de.jplag.emf.model; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EFactory; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.ETypedElement; +import org.eclipse.emf.ecore.EcoreFactory; +import org.eclipse.emf.ecore.EcorePackage; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.emf.ecore.xmi.impl.XMLResourceFactoryImpl; + +public class BookStoreFactory { + + private static final String MODEL_NAME = "bookStore.xml"; + private static final String METAMODEL_NAME = "bookStore.ecore"; + + public static void generateAll(String filePath) { + File file = new File(filePath); + if (!file.exists()) { + file.mkdirs(); + } + BookStoreFactory.createMetamodelAndModelInstance(filePath); + } + + @SuppressWarnings("unchecked") + private static void createMetamodelAndModelInstance(String baseBath) { + /* + * Create metamodel: + */ + EcoreFactory theCoreFactory = EcoreFactory.eINSTANCE; + + EClass bookStoreEClass = theCoreFactory.createEClass(); + bookStoreEClass.setName("BookStore"); + + EClass bookEClass = theCoreFactory.createEClass(); + bookEClass.setName("Book"); + + EPackage bookStoreEPackage = theCoreFactory.createEPackage(); + bookStoreEPackage.setName("BookStorePackage"); + bookStoreEPackage.setNsPrefix("bookStore"); + bookStoreEPackage.setNsURI("http:///com.ibm.dynamic.example.bookstore.ecore"); + + EcorePackage theCorePackage = EcorePackage.eINSTANCE; + + EAttribute bookStoreOwner = theCoreFactory.createEAttribute(); + bookStoreOwner.setName("owner"); + bookStoreOwner.setEType(theCorePackage.getEString()); + EAttribute bookStoreLocation = theCoreFactory.createEAttribute(); + bookStoreLocation.setName("location"); + bookStoreLocation.setEType(theCorePackage.getEString()); + EReference bookStore_Books = theCoreFactory.createEReference(); + bookStore_Books.setName("books"); + bookStore_Books.setEType(bookEClass); + bookStore_Books.setUpperBound(ETypedElement.UNBOUNDED_MULTIPLICITY); + bookStore_Books.setContainment(true); + + EAttribute bookName = theCoreFactory.createEAttribute(); + bookName.setName("name"); + bookName.setEType(theCorePackage.getEString()); + EAttribute bookISBN = theCoreFactory.createEAttribute(); + bookISBN.setName("isbn"); + bookISBN.setID(true); + bookISBN.setEType(theCorePackage.getEInt()); + + bookStoreEClass.getEStructuralFeatures().add(bookStoreOwner); + bookStoreEClass.getEStructuralFeatures().add(bookStoreLocation); + bookStoreEClass.getEStructuralFeatures().add(bookStore_Books); + + bookEClass.getEStructuralFeatures().add(bookName); + bookEClass.getEStructuralFeatures().add(bookISBN); + + bookStoreEPackage.getEClassifiers().add(bookStoreEClass); + bookStoreEPackage.getEClassifiers().add(bookEClass); + + /* + * Create model instance: + */ + EFactory bookFactoryInstance = bookStoreEPackage.getEFactoryInstance(); + + EObject bookObject = bookFactoryInstance.create(bookEClass); + EObject bookStoreObject = bookFactoryInstance.create(bookStoreEClass); + + bookStoreObject.eSet(bookStoreOwner, "David Brown"); + bookStoreObject.eSet(bookStoreLocation, "Street#12, Top Town, NY"); + ((List) bookStoreObject.eGet(bookStore_Books)).add(bookObject); + + bookObject.eSet(bookName, "Harry Potter and the Deathly Hallows"); + bookObject.eSet(bookISBN, 157221); + + /* + * Save model instance and metamodel: + */ + persist(baseBath, bookStoreObject, MODEL_NAME, "*"); + persist(baseBath, bookStoreEPackage, METAMODEL_NAME, EcorePackage.eNAME); + } + + private static void persist(String baseBath, EObject eObject, String name, String extension) { + ResourceSet metaResourceSet = new ResourceSetImpl(); + metaResourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(extension, new XMLResourceFactoryImpl()); + Resource metaResource = metaResourceSet.createResource(URI.createFileURI(baseBath + File.separator + name)); + metaResource.getContents().add(eObject); + + try { + metaResource.save(null); + } catch (IOException exception) { + exception.printStackTrace(); + } + } + +} diff --git a/languages/emf-model/src/test/java/de/jplag/emf/model/MinimalModelInstanceTest.java b/languages/emf-model/src/test/java/de/jplag/emf/model/MinimalModelInstanceTest.java new file mode 100644 index 000000000..2c13e44a5 --- /dev/null +++ b/languages/emf-model/src/test/java/de/jplag/emf/model/MinimalModelInstanceTest.java @@ -0,0 +1,67 @@ +package de.jplag.emf.model; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.File; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.TreeSet; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import de.jplag.ParsingException; +import de.jplag.Token; +import de.jplag.TokenPrinter; +import de.jplag.emf.EmfLanguage; +import de.jplag.testutils.FileUtil; + +class MinimalModelInstanceTest { + private final Logger logger = LoggerFactory.getLogger(MinimalModelInstanceTest.class); + + private static final Path BASE_PATH = Path.of("src", "test", "resources", "de", "jplag", "books"); + private static final String[] TEST_SUBJECTS = {"bookStore.ecore", "bookStore.xml", "bookStore2.xml"}; + + private EmfModelLanguage language; + private File baseDirectory; + + @BeforeEach + public void setUp() { + language = new EmfModelLanguage(); + baseDirectory = BASE_PATH.toFile(); + FileUtil.assertDirectory(baseDirectory, TEST_SUBJECTS); + } + + @Test + @DisplayName("Test tokens extracted from generated example instances") + void testBookStoreInstances() { + File baseFile = new File(BASE_PATH.toString()); + List baseFiles = new ArrayList<>(Arrays.asList(baseFile.listFiles())); + var sortedFiles = new TreeSet<>(language.customizeSubmissionOrder(baseFiles)); + try { + List tokens = language.parse(sortedFiles); + assertNotEquals(0, tokens.size()); + logger.debug(TokenPrinter.printTokens(tokens, baseDirectory, Optional.of(EmfLanguage.VIEW_FILE_SUFFIX))); + logger.info("Parsed tokens: " + tokens); + assertEquals(7, tokens.size()); + } catch (ParsingException e) { + fail("Parsing failed: " + e.getMessage(), e); + } + + } + + @AfterEach + public void tearDown() { + FileUtil.clearFiles(new File(BASE_PATH.toString()), EmfModelLanguage.VIEW_FILE_SUFFIX); + } + +} diff --git a/languages/emf-model/src/test/resources/de/jplag/books/bookStore.ecore b/languages/emf-model/src/test/resources/de/jplag/books/bookStore.ecore new file mode 100644 index 000000000..e50d0ead5 --- /dev/null +++ b/languages/emf-model/src/test/resources/de/jplag/books/bookStore.ecore @@ -0,0 +1,16 @@ + + + + + + + + + + + + diff --git a/languages/emf-model/src/test/resources/de/jplag/books/bookStore.xml b/languages/emf-model/src/test/resources/de/jplag/books/bookStore.xml new file mode 100644 index 000000000..4cd26c39e --- /dev/null +++ b/languages/emf-model/src/test/resources/de/jplag/books/bookStore.xml @@ -0,0 +1,4 @@ + + + + diff --git a/languages/emf-model/src/test/resources/de/jplag/books/bookStore2.xml b/languages/emf-model/src/test/resources/de/jplag/books/bookStore2.xml new file mode 100644 index 000000000..ac7aa3959 --- /dev/null +++ b/languages/emf-model/src/test/resources/de/jplag/books/bookStore2.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/languages/golang/README.md b/languages/golang/README.md index c943550ca..b468006ee 100644 --- a/languages/golang/README.md +++ b/languages/golang/README.md @@ -21,7 +21,7 @@ More syntactic elements of Go may turn out to be helpful to include in the futur ### Usage -To use the Go frontend, add the `-l golang` flag in the CLI, or use a `JPlagOption` object with `new de.jplag.golang.Language()` as `language` in the Java API as described in the usage information in the [readme of the main project](https://github.com/jplag/JPlag#usage) and [in the wiki](https://github.com/jplag/JPlag/wiki/1.-How-to-Use-JPlag). +To use the Go frontend, add the `-l golang` flag in the CLI, or use a `JPlagOption` object with `new de.jplag.golang.GoLanguage()` as `language` in the Java API as described in the usage information in the [readme of the main project](https://github.com/jplag/JPlag#usage) and [in the wiki](https://github.com/jplag/JPlag/wiki/1.-How-to-Use-JPlag).
diff --git a/languages/golang/src/main/java/de/jplag/golang/Language.java b/languages/golang/src/main/java/de/jplag/golang/GoLanguage.java similarity index 92% rename from languages/golang/src/main/java/de/jplag/golang/Language.java rename to languages/golang/src/main/java/de/jplag/golang/GoLanguage.java index e3590bd5a..581a57a19 100644 --- a/languages/golang/src/main/java/de/jplag/golang/Language.java +++ b/languages/golang/src/main/java/de/jplag/golang/GoLanguage.java @@ -10,7 +10,7 @@ import de.jplag.Token; @MetaInfServices(de.jplag.Language.class) -public class Language implements de.jplag.Language { +public class GoLanguage implements de.jplag.Language { private static final String NAME = "Go Parser"; private static final String IDENTIFIER = "go"; @@ -18,7 +18,7 @@ public class Language implements de.jplag.Language { private static final String[] FILE_EXTENSIONS = {".go"}; private final GoParserAdapter parserAdapter; - public Language() { + public GoLanguage() { this.parserAdapter = new GoParserAdapter(); } diff --git a/languages/golang/src/main/java/de/jplag/golang/GoParserAdapter.java b/languages/golang/src/main/java/de/jplag/golang/GoParserAdapter.java index b179e0640..3d9da82c6 100644 --- a/languages/golang/src/main/java/de/jplag/golang/GoParserAdapter.java +++ b/languages/golang/src/main/java/de/jplag/golang/GoParserAdapter.java @@ -1,7 +1,7 @@ package de.jplag.golang; +import java.io.BufferedReader; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -19,6 +19,7 @@ import de.jplag.TokenType; import de.jplag.golang.grammar.GoLexer; import de.jplag.golang.grammar.GoParser; +import de.jplag.util.FileUtils; public class GoParserAdapter extends AbstractParser { private File currentFile; @@ -34,10 +35,10 @@ public List parse(Set files) throws ParsingException { } private void parseFile(File file) throws ParsingException { - try (FileInputStream inputStream = new FileInputStream(file)) { + try (BufferedReader reader = FileUtils.openFileReader(file)) { currentFile = file; - GoLexer lexer = new GoLexer(CharStreams.fromStream(inputStream)); + GoLexer lexer = new GoLexer(CharStreams.fromReader(reader)); CommonTokenStream tokenStream = new CommonTokenStream(lexer); GoParser parser = new GoParser(tokenStream); diff --git a/languages/golang/src/main/java/de/jplag/golang/GoTokenType.java b/languages/golang/src/main/java/de/jplag/golang/GoTokenType.java index b93ced02f..9cf73ee1a 100644 --- a/languages/golang/src/main/java/de/jplag/golang/GoTokenType.java +++ b/languages/golang/src/main/java/de/jplag/golang/GoTokenType.java @@ -92,6 +92,7 @@ public enum GoTokenType implements TokenType { private final String description; + @Override public String getDescription() { return this.description; } diff --git a/languages/golang/src/test/java/de/jplag/golang/GoLanguageTest.java b/languages/golang/src/test/java/de/jplag/golang/GoLanguageTest.java index 38d9e7549..0feafc7bc 100644 --- a/languages/golang/src/test/java/de/jplag/golang/GoLanguageTest.java +++ b/languages/golang/src/test/java/de/jplag/golang/GoLanguageTest.java @@ -50,11 +50,11 @@ class GoLanguageTest { private final Logger logger = LoggerFactory.getLogger(GoLanguageTest.class); private final String[] testFiles = new String[] {COMPLETE_TEST_FILE}; private final File testFileLocation = Path.of("src", "test", "resources", "de", "jplag", "golang").toFile(); - private Language language; + private GoLanguage language; @BeforeEach void setup() { - language = new Language(); + language = new GoLanguage(); } @Test @@ -109,7 +109,7 @@ private void testSourceCoverage(String fileName, List tokens) { /** * Gets the line numbers of lines containing actual code, omitting empty lines and comment lines. * @param lines lines of a code file - * @return an array of the line numbers of code lines + * @return a list of the line numbers of code lines */ private List getCodeLines(List lines) { // This boxed boolean can be accessed from within the lambda method below diff --git a/languages/java/README.md b/languages/java/README.md new file mode 100644 index 000000000..1ea2493ba --- /dev/null +++ b/languages/java/README.md @@ -0,0 +1,3 @@ +# Java Language Module + +Extracts tokens from java source files using the java compiler. \ No newline at end of file diff --git a/languages/java/src/main/java/de/jplag/java/Language.java b/languages/java/src/main/java/de/jplag/java/JavaLanguage.java similarity index 83% rename from languages/java/src/main/java/de/jplag/java/Language.java rename to languages/java/src/main/java/de/jplag/java/JavaLanguage.java index fd0d2a577..f26b26f2c 100644 --- a/languages/java/src/main/java/de/jplag/java/Language.java +++ b/languages/java/src/main/java/de/jplag/java/JavaLanguage.java @@ -13,12 +13,12 @@ * Language for Java 9 and newer. */ @MetaInfServices(de.jplag.Language.class) -public class Language implements de.jplag.Language { +public class JavaLanguage implements de.jplag.Language { private static final String IDENTIFIER = "java"; private final Parser parser; - public Language() { + public JavaLanguage() { parser = new Parser(); } @@ -46,4 +46,9 @@ public int minimumTokenMatch() { public List parse(Set files) throws ParsingException { return this.parser.parse(files); } + + @Override + public boolean tokensHaveSemantics() { + return true; + } } diff --git a/languages/java/src/main/java/de/jplag/java/JavaTokenType.java b/languages/java/src/main/java/de/jplag/java/JavaTokenType.java index 84e4b5046..8e5ed5fe5 100644 --- a/languages/java/src/main/java/de/jplag/java/JavaTokenType.java +++ b/languages/java/src/main/java/de/jplag/java/JavaTokenType.java @@ -12,12 +12,8 @@ public enum JavaTokenType implements TokenType { J_VARDEF("VARDEF"), // check J_SYNC_BEGIN("SYNC{"), // check J_SYNC_END("}SYNC"), // check - J_DO_BEGIN("DO{"), // check - J_DO_END("}DO"), // check - J_WHILE_BEGIN("WHILE{"), // check - J_WHILE_END("}WHILE"), // check - J_FOR_BEGIN("FOR{"), // check - J_FOR_END("}FOR"), // check + J_LOOP_BEGIN("LOOP{"), // check + J_LOOP_END("}LOOP"), // check J_SWITCH_BEGIN("SWITCH{"), // check J_SWITCH_END("}SWITCH"), // check J_CASE("CASE"), // check @@ -28,7 +24,6 @@ public enum JavaTokenType implements TokenType { J_FINALLY_BEGIN("FINALLY{"), // check J_FINALLY_END("}FINALLY"), // check J_IF_BEGIN("IF{"), // check - J_ELSE("ELSE"), // check J_IF_END("}IF"), // check J_COND("COND"), // check J_BREAK("BREAK"), // check @@ -81,6 +76,7 @@ public enum JavaTokenType implements TokenType { private final String description; + @Override public String getDescription() { return this.description; } diff --git a/languages/java/src/main/java/de/jplag/java/JavacAdapter.java b/languages/java/src/main/java/de/jplag/java/JavacAdapter.java index bd6972b87..ae3b17015 100644 --- a/languages/java/src/main/java/de/jplag/java/JavacAdapter.java +++ b/languages/java/src/main/java/de/jplag/java/JavacAdapter.java @@ -2,7 +2,7 @@ import java.io.File; import java.io.IOException; -import java.nio.charset.StandardCharsets; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -20,6 +20,7 @@ import de.jplag.ParsingException; import de.jplag.Token; +import de.jplag.util.FileUtils; import com.sun.source.tree.CompilationUnitTree; import com.sun.source.tree.LineMap; @@ -35,7 +36,8 @@ public void parseFiles(Set files, final Parser parser) throws ParsingExcep var listener = new DiagnosticCollector<>(); List parsingExceptions = new ArrayList<>(); - try (final StandardJavaFileManager fileManager = javac.getStandardFileManager(listener, null, StandardCharsets.UTF_8)) { + final Charset guessedCharset = FileUtils.detectCharsetFromMultiple(files); + try (final StandardJavaFileManager fileManager = javac.getStandardFileManager(listener, null, guessedCharset)) { var javaFiles = fileManager.getJavaFileObjectsFromFiles(files); // We need to disable annotation processing, see @@ -49,7 +51,7 @@ public void parseFiles(Set files, final Parser parser) throws ParsingExcep var scanner = new TokenGeneratingTreeScanner(file, parser, map, positions, ast); ast.accept(scanner, null); parsingExceptions.addAll(scanner.getParsingExceptions()); - parser.add(Token.fileEnd(file)); + parser.add(Token.semanticFileEnd(file)); } } catch (IOException exception) { throw new ParsingException(null, exception.getMessage(), exception); diff --git a/languages/java/src/main/java/de/jplag/java/Parser.java b/languages/java/src/main/java/de/jplag/java/Parser.java index ffeaa4802..f6a35e370 100644 --- a/languages/java/src/main/java/de/jplag/java/Parser.java +++ b/languages/java/src/main/java/de/jplag/java/Parser.java @@ -8,7 +8,6 @@ import de.jplag.AbstractParser; import de.jplag.ParsingException; import de.jplag.Token; -import de.jplag.TokenType; public class Parser extends AbstractParser { private List tokens; @@ -23,13 +22,13 @@ public Parser() { public List parse(Set files) throws ParsingException { tokens = new ArrayList<>(); new JavacAdapter().parseFiles(files, this); + logger.debug("--- token semantics ---"); + for (Token token : tokens) { + logger.debug("{} | {} | {}", token.getLine(), token.getType().getDescription(), token.getSemantics()); + } return tokens; } - public void add(TokenType type, File file, long line, long column, long length) { - add(new Token(type, file, (int) line, (int) column, (int) length)); - } - public void add(Token token) { tokens.add(token); } diff --git a/languages/java/src/main/java/de/jplag/java/TokenGeneratingTreeScanner.java b/languages/java/src/main/java/de/jplag/java/TokenGeneratingTreeScanner.java index f3d40334d..c026b975a 100644 --- a/languages/java/src/main/java/de/jplag/java/TokenGeneratingTreeScanner.java +++ b/languages/java/src/main/java/de/jplag/java/TokenGeneratingTreeScanner.java @@ -6,10 +6,17 @@ import java.util.Set; import de.jplag.ParsingException; +import de.jplag.Token; +import de.jplag.TokenType; +import de.jplag.semantics.CodeSemantics; +import de.jplag.semantics.VariableAccessType; +import de.jplag.semantics.VariableRegistry; +import de.jplag.semantics.VariableScope; import com.sun.source.tree.AnnotationTree; import com.sun.source.tree.AssertTree; import com.sun.source.tree.AssignmentTree; +import com.sun.source.tree.BlockTree; import com.sun.source.tree.BreakTree; import com.sun.source.tree.CaseTree; import com.sun.source.tree.CatchTree; @@ -24,9 +31,11 @@ import com.sun.source.tree.ErroneousTree; import com.sun.source.tree.ExportsTree; import com.sun.source.tree.ForLoopTree; +import com.sun.source.tree.IdentifierTree; import com.sun.source.tree.IfTree; import com.sun.source.tree.ImportTree; import com.sun.source.tree.LineMap; +import com.sun.source.tree.MemberSelectTree; import com.sun.source.tree.MethodInvocationTree; import com.sun.source.tree.MethodTree; import com.sun.source.tree.ModuleTree; @@ -50,14 +59,23 @@ import com.sun.source.util.SourcePositions; import com.sun.source.util.TreeScanner; -final class TokenGeneratingTreeScanner extends TreeScanner { +final class TokenGeneratingTreeScanner extends TreeScanner { private final File file; private final Parser parser; private final LineMap map; private final SourcePositions positions; private final CompilationUnitTree ast; - private List parsingExceptions = new ArrayList<>(); + private final List parsingExceptions = new ArrayList<>(); + + private final VariableRegistry variableRegistry; + + private static final Set IMMUTABLES = Set.of( + // from https://medium.com/@bpnorlander/java-understanding-primitive-types-and-wrapper-objects-a6798fb2afe9 + "byte", "short", "int", "long", "float", "double", "boolean", "char", // primitives + "Byte", "Short", "Integer", "Long", "Float", "Double", "Boolean", "Character", "String"); + + private static final Set CRITICAL_METHODS = Set.of("System.out.println", "System.out.print"); public TokenGeneratingTreeScanner(File file, Parser parser, LineMap map, SourcePositions positions, CompilationUnitTree ast) { this.file = file; @@ -65,20 +83,26 @@ public TokenGeneratingTreeScanner(File file, Parser parser, LineMap map, SourceP this.map = map; this.positions = positions; this.ast = ast; + this.variableRegistry = new VariableRegistry(); } public List getParsingExceptions() { return parsingExceptions; } + public void addToken(TokenType type, File file, long line, long column, long length, CodeSemantics semantics) { + parser.add(new Token(type, file, (int) line, (int) column, (int) length, semantics)); + variableRegistry.updateSemantics(semantics); + } + /** * Convenience method that adds a specific token. * @param tokenType is the type of the token. * @param position is the start position of the token. * @param length is the length of the token. */ - private void addToken(JavaTokenType tokenType, long position, int length) { - parser.add(tokenType, file, map.getLineNumber(position), map.getColumnNumber(position), length); + private void addToken(JavaTokenType tokenType, long position, int length, CodeSemantics semantics) { + addToken(tokenType, file, map.getLineNumber(position), map.getColumnNumber(position), length, semantics); } /** @@ -87,363 +111,456 @@ private void addToken(JavaTokenType tokenType, long position, int length) { * @param start is the start position of the token. * @param end is the end position of the token for the calculation of the length. */ - private void addToken(JavaTokenType tokenType, long start, long end) { - parser.add(tokenType, file, map.getLineNumber(start), map.getColumnNumber(start), (end - start)); + private void addToken(JavaTokenType tokenType, long start, long end, CodeSemantics semantics) { + addToken(tokenType, file, map.getLineNumber(start), map.getColumnNumber(start), (end - start), semantics); + } + + private boolean isMutable(Tree classTree) { + // classTree is null if `var` keyword is used + return classTree == null || !IMMUTABLES.contains(classTree.toString()); + } + + @Override + public Void visitBlock(BlockTree node, Void unused) { + // kind of weird since in the case of for loops and catches, two scopes are introduced + // but I'm pretty sure that's how Java does it internally as well + variableRegistry.enterLocalScope(); + super.visitBlock(node, null); + variableRegistry.exitLocalScope(); + return null; } @Override - public Object visitClass(ClassTree node, Object p) { + public Void visitClass(ClassTree node, Void unused) { + // not super accurate + variableRegistry.registerVariable(node.getSimpleName().toString(), VariableScope.FILE, true); + variableRegistry.enterClass(); + for (var member : node.getMembers()) { + if (member.getKind() == Tree.Kind.VARIABLE) { + VariableTree variableTree = (VariableTree) member; + String name = variableTree.getName().toString(); + boolean mutable = isMutable(variableTree.getType()); + variableRegistry.registerVariable(name, VariableScope.CLASS, mutable); + } + } + long start = positions.getStartPosition(ast, node); long end = positions.getEndPosition(ast, node) - 1; - + CodeSemantics semantics = CodeSemantics.createControl(); if (node.getKind() == Tree.Kind.ENUM) { - addToken(JavaTokenType.J_ENUM_BEGIN, start, 4); + addToken(JavaTokenType.J_ENUM_BEGIN, start, 4, semantics); } else if (node.getKind() == Tree.Kind.INTERFACE) { - addToken(JavaTokenType.J_INTERFACE_BEGIN, start, 9); + addToken(JavaTokenType.J_INTERFACE_BEGIN, start, 9, semantics); } else if (node.getKind() == Tree.Kind.RECORD) { - addToken(JavaTokenType.J_RECORD_BEGIN, start, 1); + addToken(JavaTokenType.J_RECORD_BEGIN, start, 1, semantics); } else if (node.getKind() == Tree.Kind.ANNOTATION_TYPE) { - addToken(JavaTokenType.J_ANNO_T_BEGIN, start, 10); + addToken(JavaTokenType.J_ANNO_T_BEGIN, start, 10, semantics); } else if (node.getKind() == Tree.Kind.CLASS) { - addToken(JavaTokenType.J_CLASS_BEGIN, start, 5); + addToken(JavaTokenType.J_CLASS_BEGIN, start, 5, semantics); } - Object result = super.visitClass(node, p); - if (node.getKind() == Tree.Kind.ENUM) { - addToken(JavaTokenType.J_ENUM_END, end, 1); - } else if (node.getKind() == Tree.Kind.INTERFACE) { - addToken(JavaTokenType.J_INTERFACE_END, end, 1); - } else if (node.getKind() == Tree.Kind.RECORD) { - addToken(JavaTokenType.J_RECORD_END, end, 1); - } else if (node.getKind() == Tree.Kind.ANNOTATION_TYPE) { - addToken(JavaTokenType.J_ANNO_T_END, end, 1); - } else if (node.getKind() == Tree.Kind.CLASS) { - addToken(JavaTokenType.J_CLASS_END, end, 1); + super.visitClass(node, null); + + JavaTokenType tokenType = switch (node.getKind()) { + case ENUM -> JavaTokenType.J_ENUM_END; + case INTERFACE -> JavaTokenType.J_INTERFACE_END; + case RECORD -> JavaTokenType.J_RECORD_END; + case ANNOTATION_TYPE -> JavaTokenType.J_ANNO_T_END; + case CLASS -> JavaTokenType.J_CLASS_END; + default -> null; + }; + if (tokenType != null) { + semantics = CodeSemantics.createControl(); + addToken(tokenType, end, 1, semantics); } - return result; + variableRegistry.exitClass(); + return null; } @Override - public Object visitImport(ImportTree node, Object p) { + public Void visitImport(ImportTree node, Void unused) { long start = positions.getStartPosition(ast, node); - addToken(JavaTokenType.J_IMPORT, start, 6); - return super.visitImport(node, p); + addToken(JavaTokenType.J_IMPORT, start, 6, CodeSemantics.createKeep()); + return super.visitImport(node, null); } @Override - public Object visitPackage(PackageTree node, Object p) { + public Void visitPackage(PackageTree node, Void unused) { long start = positions.getStartPosition(ast, node); - addToken(JavaTokenType.J_PACKAGE, start, 7); - return super.visitPackage(node, p); + addToken(JavaTokenType.J_PACKAGE, start, 7, CodeSemantics.createControl()); + return super.visitPackage(node, null); } @Override - public Object visitMethod(MethodTree node, Object p) { + public Void visitMethod(MethodTree node, Void unused) { + variableRegistry.enterLocalScope(); long start = positions.getStartPosition(ast, node); long end = positions.getEndPosition(ast, node) - 1; - addToken(JavaTokenType.J_METHOD_BEGIN, start, node.getName().length()); - Object result = super.visitMethod(node, p); - addToken(JavaTokenType.J_METHOD_END, end, 1); - return result; + addToken(JavaTokenType.J_METHOD_BEGIN, start, node.getName().length(), CodeSemantics.createControl()); + super.visitMethod(node, null); + addToken(JavaTokenType.J_METHOD_END, end, 1, CodeSemantics.createControl()); + variableRegistry.addAllNonLocalVariablesAsReads(); + variableRegistry.exitLocalScope(); + return null; } @Override - public Object visitSynchronized(SynchronizedTree node, Object p) { + public Void visitSynchronized(SynchronizedTree node, Void unused) { long start = positions.getStartPosition(ast, node); long end = positions.getEndPosition(ast, node) - 1; - addToken(JavaTokenType.J_SYNC_BEGIN, start, 12); - Object result = super.visitSynchronized(node, p); - addToken(JavaTokenType.J_SYNC_END, end, 1); - return result; + addToken(JavaTokenType.J_SYNC_BEGIN, start, 12, CodeSemantics.createControl()); + super.visitSynchronized(node, null); + addToken(JavaTokenType.J_SYNC_END, end, 1, CodeSemantics.createControl()); + return null; } @Override - public Object visitDoWhileLoop(DoWhileLoopTree node, Object p) { + public Void visitDoWhileLoop(DoWhileLoopTree node, Void unused) { long start = positions.getStartPosition(ast, node); - long end = positions.getEndPosition(ast, node) - 1; - addToken(JavaTokenType.J_DO_BEGIN, start, 2); - Object result = super.visitDoWhileLoop(node, p); - addToken(JavaTokenType.J_DO_END, end, 1); - return result; + long end = positions.getEndPosition(ast, node.getStatement()) - 1; + addToken(JavaTokenType.J_LOOP_BEGIN, start, 2, CodeSemantics.createLoopBegin()); + scan(node.getStatement(), null); + addToken(JavaTokenType.J_LOOP_END, end, 1, CodeSemantics.createLoopEnd()); + scan(node.getCondition(), null); + return null; } @Override - public Object visitWhileLoop(WhileLoopTree node, Object p) { + public Void visitWhileLoop(WhileLoopTree node, Void unused) { long start = positions.getStartPosition(ast, node); long end = positions.getEndPosition(ast, node) - 1; - addToken(JavaTokenType.J_WHILE_BEGIN, start, 5); - Object result = super.visitWhileLoop(node, p); - addToken(JavaTokenType.J_WHILE_END, end, 1); - return result; + addToken(JavaTokenType.J_LOOP_BEGIN, start, 5, CodeSemantics.createLoopBegin()); + super.visitWhileLoop(node, null); + addToken(JavaTokenType.J_LOOP_END, end, 1, CodeSemantics.createLoopEnd()); + return null; } @Override - public Object visitForLoop(ForLoopTree node, Object p) { + public Void visitForLoop(ForLoopTree node, Void unused) { + variableRegistry.enterLocalScope(); long start = positions.getStartPosition(ast, node); long end = positions.getEndPosition(ast, node) - 1; - addToken(JavaTokenType.J_FOR_BEGIN, start, 3); - Object result = super.visitForLoop(node, p); - addToken(JavaTokenType.J_FOR_END, end, 1); - return result; + addToken(JavaTokenType.J_LOOP_BEGIN, start, 3, CodeSemantics.createLoopBegin()); + super.visitForLoop(node, null); + addToken(JavaTokenType.J_LOOP_END, end, 1, CodeSemantics.createLoopEnd()); + variableRegistry.exitLocalScope(); + return null; } @Override - public Object visitEnhancedForLoop(EnhancedForLoopTree node, Object p) { + public Void visitEnhancedForLoop(EnhancedForLoopTree node, Void unused) { + variableRegistry.enterLocalScope(); long start = positions.getStartPosition(ast, node); long end = positions.getEndPosition(ast, node) - 1; - addToken(JavaTokenType.J_FOR_BEGIN, start, 3); - Object result = super.visitEnhancedForLoop(node, p); - addToken(JavaTokenType.J_FOR_END, end, 1); - return result; + addToken(JavaTokenType.J_LOOP_BEGIN, start, 3, CodeSemantics.createLoopBegin()); + super.visitEnhancedForLoop(node, null); + addToken(JavaTokenType.J_LOOP_END, end, 1, CodeSemantics.createLoopEnd()); + variableRegistry.exitLocalScope(); + return null; } @Override - public Object visitSwitch(SwitchTree node, Object p) { + public Void visitSwitch(SwitchTree node, Void unused) { long start = positions.getStartPosition(ast, node); long end = positions.getEndPosition(ast, node) - 1; - addToken(JavaTokenType.J_SWITCH_BEGIN, start, 6); - Object result = super.visitSwitch(node, p); - addToken(JavaTokenType.J_SWITCH_END, end, 1); - return result; + addToken(JavaTokenType.J_SWITCH_BEGIN, start, 6, CodeSemantics.createControl()); + super.visitSwitch(node, null); + addToken(JavaTokenType.J_SWITCH_END, end, 1, CodeSemantics.createControl()); + return null; } @Override - public Object visitSwitchExpression(SwitchExpressionTree node, Object parameterValue) { + public Void visitSwitchExpression(SwitchExpressionTree node, Void unused) { long start = positions.getStartPosition(ast, node); long end = positions.getEndPosition(ast, node) - 1; - addToken(JavaTokenType.J_SWITCH_BEGIN, start, 6); - Object result = super.visitSwitchExpression(node, parameterValue); - addToken(JavaTokenType.J_SWITCH_END, end, 1); - return result; + addToken(JavaTokenType.J_SWITCH_BEGIN, start, 6, CodeSemantics.createControl()); + super.visitSwitchExpression(node, null); + addToken(JavaTokenType.J_SWITCH_END, end, 1, CodeSemantics.createControl()); + return null; } @Override - public Object visitCase(CaseTree node, Object p) { + public Void visitCase(CaseTree node, Void unused) { long start = positions.getStartPosition(ast, node); - addToken(JavaTokenType.J_CASE, start, 4); - return super.visitCase(node, p); + addToken(JavaTokenType.J_CASE, start, 4, CodeSemantics.createControl()); + return super.visitCase(node, null); } @Override - public Object visitTry(TryTree node, Object p) { + public Void visitTry(TryTree node, Void unused) { long start = positions.getStartPosition(ast, node); - addToken(JavaTokenType.J_TRY_BEGIN, start, 3); - scan(node.getResources(), p); - scan(node.getBlock(), p); + addToken(JavaTokenType.J_TRY_BEGIN, start, 3, CodeSemantics.createControl()); + scan(node.getResources(), null); + scan(node.getBlock(), null); long end = positions.getEndPosition(ast, node); - addToken(JavaTokenType.J_TRY_END, end, 1); - scan(node.getCatches(), p); + scan(node.getCatches(), null); if (node.getFinallyBlock() != null) { start = positions.getStartPosition(ast, node.getFinallyBlock()); - addToken(JavaTokenType.J_FINALLY_BEGIN, start, 3); - scan(node.getFinallyBlock(), p); + addToken(JavaTokenType.J_FINALLY_BEGIN, start, 3, CodeSemantics.createControl()); + scan(node.getFinallyBlock(), null); end = positions.getEndPosition(ast, node.getFinallyBlock()); - addToken(JavaTokenType.J_FINALLY_END, end, 1); + addToken(JavaTokenType.J_FINALLY_END, end, 1, CodeSemantics.createControl()); } - return null; // return value isn't used + addToken(JavaTokenType.J_TRY_END, end, 1, CodeSemantics.createControl()); + return null; } @Override - public Object visitCatch(CatchTree node, Object p) { + public Void visitCatch(CatchTree node, Void unused) { + variableRegistry.enterLocalScope(); long start = positions.getStartPosition(ast, node); long end = positions.getEndPosition(ast, node) - 1; - addToken(JavaTokenType.J_CATCH_BEGIN, start, 5); - Object result = super.visitCatch(node, p); - addToken(JavaTokenType.J_CATCH_END, end, 1); - return result; + addToken(JavaTokenType.J_CATCH_BEGIN, start, 5, CodeSemantics.createControl()); + super.visitCatch(node, null); + addToken(JavaTokenType.J_CATCH_END, end, 1, CodeSemantics.createControl()); + variableRegistry.exitLocalScope(); + return null; } @Override - public Object visitIf(IfTree node, Object p) { + public Void visitIf(IfTree node, Void unused) { long start = positions.getStartPosition(ast, node); - long end = positions.getEndPosition(ast, node) - 1; - addToken(JavaTokenType.J_IF_BEGIN, start, 2); - scan(node.getCondition(), p); - scan(node.getThenStatement(), p); + + addToken(JavaTokenType.J_IF_BEGIN, start, 2, CodeSemantics.createControl()); + scan(node.getCondition(), null); + scan(node.getThenStatement(), null); + long end = positions.getEndPosition(ast, node.getThenStatement()) - 1; + addToken(JavaTokenType.J_IF_END, end, 1, CodeSemantics.createControl()); + boolean isElseOnly = false; if (node.getElseStatement() != null) { - start = positions.getStartPosition(ast, node.getElseStatement()); - addToken(JavaTokenType.J_ELSE, start, 4); + isElseOnly = node.getElseStatement().getKind() != Tree.Kind.IF; + if (isElseOnly) { + start = positions.getStartPosition(ast, node.getElseStatement()); + addToken(JavaTokenType.J_IF_BEGIN, start, 4, CodeSemantics.createControl()); + } + } + scan(node.getElseStatement(), null); + if (isElseOnly) { + end = positions.getEndPosition(ast, node) - 1; + addToken(JavaTokenType.J_IF_END, end, 1, CodeSemantics.createControl()); } - scan(node.getElseStatement(), p); - addToken(JavaTokenType.J_IF_END, end, 1); return null; } @Override - public Object visitBreak(BreakTree node, Object p) { + public Void visitBreak(BreakTree node, Void unused) { long start = positions.getStartPosition(ast, node); - addToken(JavaTokenType.J_BREAK, start, 5); - return super.visitBreak(node, p); + addToken(JavaTokenType.J_BREAK, start, 5, CodeSemantics.createControl()); + return super.visitBreak(node, null); } @Override - public Object visitContinue(ContinueTree node, Object p) { + public Void visitContinue(ContinueTree node, Void unused) { long start = positions.getStartPosition(ast, node); - addToken(JavaTokenType.J_CONTINUE, start, 8); - return super.visitContinue(node, p); + addToken(JavaTokenType.J_CONTINUE, start, 8, CodeSemantics.createControl()); + return super.visitContinue(node, null); } @Override - public Object visitReturn(ReturnTree node, Object p) { + public Void visitReturn(ReturnTree node, Void unused) { long start = positions.getStartPosition(ast, node); - addToken(JavaTokenType.J_RETURN, start, 6); - return super.visitReturn(node, p); + addToken(JavaTokenType.J_RETURN, start, 6, CodeSemantics.createControl()); + return super.visitReturn(node, null); } @Override - public Object visitThrow(ThrowTree node, Object p) { + public Void visitThrow(ThrowTree node, Void unused) { long start = positions.getStartPosition(ast, node); - addToken(JavaTokenType.J_THROW, start, 5); - return super.visitThrow(node, p); + addToken(JavaTokenType.J_THROW, start, 5, CodeSemantics.createControl()); + return super.visitThrow(node, null); } @Override - public Object visitNewClass(NewClassTree node, Object p) { + public Void visitNewClass(NewClassTree node, Void unused) { long start = positions.getStartPosition(ast, node); - if (node.getTypeArguments().size() > 0) { - addToken(JavaTokenType.J_GENERIC, start, 3 + node.getIdentifier().toString().length()); + if (!node.getTypeArguments().isEmpty()) { + addToken(JavaTokenType.J_GENERIC, start, 3 + node.getIdentifier().toString().length(), new CodeSemantics()); } - addToken(JavaTokenType.J_NEWCLASS, start, 3); - return super.visitNewClass(node, p); + addToken(JavaTokenType.J_NEWCLASS, start, 3, new CodeSemantics()); + super.visitNewClass(node, null); + return null; } @Override - public Object visitTypeParameter(TypeParameterTree node, Object p) { + public Void visitTypeParameter(TypeParameterTree node, Void unused) { long start = positions.getStartPosition(ast, node); // This is odd, but also done like this in Java 1.7 - addToken(JavaTokenType.J_GENERIC, start, 1); - return super.visitTypeParameter(node, p); + addToken(JavaTokenType.J_GENERIC, start, 1, new CodeSemantics()); + return super.visitTypeParameter(node, null); } @Override - public Object visitNewArray(NewArrayTree node, Object p) { + public Void visitNewArray(NewArrayTree node, Void unused) { long start = positions.getStartPosition(ast, node); long end = positions.getEndPosition(ast, node) - 1; - addToken(JavaTokenType.J_NEWARRAY, start, 3); - scan(node.getType(), p); - scan(node.getDimensions(), p); + addToken(JavaTokenType.J_NEWARRAY, start, 3, new CodeSemantics()); + scan(node.getType(), null); + scan(node.getDimensions(), null); boolean hasInit = node.getInitializers() != null && !node.getInitializers().isEmpty(); if (hasInit) { start = positions.getStartPosition(ast, node.getInitializers().get(0)); - addToken(JavaTokenType.J_ARRAY_INIT_BEGIN, start, 1); + addToken(JavaTokenType.J_ARRAY_INIT_BEGIN, start, 1, new CodeSemantics()); } - scan(node.getInitializers(), p); + scan(node.getInitializers(), null); // super method has annotation processing but we have it disabled anyways if (hasInit) { - addToken(JavaTokenType.J_ARRAY_INIT_END, end, 1); + addToken(JavaTokenType.J_ARRAY_INIT_END, end, 1, new CodeSemantics()); } - return null; // return value isn't used + return null; } @Override - public Object visitAssignment(AssignmentTree node, Object p) { + public Void visitAssignment(AssignmentTree node, Void unused) { long start = positions.getStartPosition(ast, node); - addToken(JavaTokenType.J_ASSIGN, start, 1); - return super.visitAssignment(node, p); + addToken(JavaTokenType.J_ASSIGN, start, 1, new CodeSemantics()); + variableRegistry.setNextVariableAccessType(VariableAccessType.WRITE); + return super.visitAssignment(node, null); } @Override - public Object visitCompoundAssignment(CompoundAssignmentTree node, Object p) { + public Void visitCompoundAssignment(CompoundAssignmentTree node, Void unused) { long start = positions.getStartPosition(ast, node); - addToken(JavaTokenType.J_ASSIGN, start, 1); - return super.visitCompoundAssignment(node, p); + addToken(JavaTokenType.J_ASSIGN, start, 1, new CodeSemantics()); + variableRegistry.setNextVariableAccessType(VariableAccessType.READ_WRITE); + return super.visitCompoundAssignment(node, null); } @Override - public Object visitUnary(UnaryTree node, Object p) { + public Void visitUnary(UnaryTree node, Void unused) { if (Set.of(Tree.Kind.PREFIX_INCREMENT, Tree.Kind.POSTFIX_INCREMENT, Tree.Kind.PREFIX_DECREMENT, Tree.Kind.POSTFIX_DECREMENT) .contains(node.getKind())) { long start = positions.getStartPosition(ast, node); - addToken(JavaTokenType.J_ASSIGN, start, 1); + addToken(JavaTokenType.J_ASSIGN, start, 1, new CodeSemantics()); + variableRegistry.setNextVariableAccessType(VariableAccessType.READ_WRITE); } - return super.visitUnary(node, p); + return super.visitUnary(node, null); } @Override - public Object visitAssert(AssertTree node, Object p) { + public Void visitAssert(AssertTree node, Void unused) { long start = positions.getStartPosition(ast, node); - addToken(JavaTokenType.J_ASSERT, start, 6); - return super.visitAssert(node, p); + addToken(JavaTokenType.J_ASSERT, start, 6, CodeSemantics.createControl()); + return super.visitAssert(node, null); } @Override - public Object visitVariable(VariableTree node, Object p) { + public Void visitVariable(VariableTree node, Void unused) { long start = positions.getStartPosition(ast, node); - addToken(JavaTokenType.J_VARDEF, start, node.toString().length()); - - return super.visitVariable(node, p); + String name = node.getName().toString(); + boolean inLocalScope = variableRegistry.inLocalScope(); + // this presents a problem when classes are declared in local scopes, which can happen in ad-hoc implementations + CodeSemantics semantics; + if (inLocalScope) { + boolean mutable = isMutable(node.getType()); + variableRegistry.registerVariable(name, VariableScope.LOCAL, mutable); + semantics = new CodeSemantics(); + } else { + semantics = CodeSemantics.createKeep(); + } + addToken(JavaTokenType.J_VARDEF, start, node.toString().length(), semantics); + // manually add variable to semantics since identifier isn't visited + variableRegistry.setNextVariableAccessType(VariableAccessType.WRITE); + variableRegistry.registerVariableAccess(name, !inLocalScope); + return super.visitVariable(node, null); } @Override - public Object visitConditionalExpression(ConditionalExpressionTree node, Object p) { + public Void visitConditionalExpression(ConditionalExpressionTree node, Void unused) { long start = positions.getStartPosition(ast, node); - addToken(JavaTokenType.J_COND, start, 1); - return super.visitConditionalExpression(node, p); + addToken(JavaTokenType.J_COND, start, 1, new CodeSemantics()); + return super.visitConditionalExpression(node, null); } @Override - public Object visitMethodInvocation(MethodInvocationTree node, Object p) { + public Void visitMethodInvocation(MethodInvocationTree node, Void unused) { long start = positions.getStartPosition(ast, node); - addToken(JavaTokenType.J_APPLY, start, positions.getEndPosition(ast, node.getMethodSelect()) - start); - return super.visitMethodInvocation(node, p); + long end = positions.getEndPosition(ast, node.getMethodSelect()) - start; + CodeSemantics codeSemantics = CRITICAL_METHODS.contains(node.getMethodSelect().toString()) ? CodeSemantics.createCritical() + : CodeSemantics.createControl(); + addToken(JavaTokenType.J_APPLY, start, end, codeSemantics); + variableRegistry.addAllNonLocalVariablesAsReads(); + scan(node.getTypeArguments(), null); + // differentiate bar() and this.bar() (ignore) from bar.foo() (don't ignore) + // look at cases foo.bar()++ and foo().bar++ + variableRegistry.setIgnoreNextVariableAccess(true); + variableRegistry.setMutableWrite(true); + scan(node.getMethodSelect(), null); // foo.bar() is a write to foo + scan(node.getArguments(), null); // foo(bar) is a write to bar + variableRegistry.setMutableWrite(false); + return null; } @Override - public Object visitAnnotation(AnnotationTree node, Object p) { + public Void visitAnnotation(AnnotationTree node, Void unused) { long start = positions.getStartPosition(ast, node); - addToken(JavaTokenType.J_ANNO, start, 1); - return super.visitAnnotation(node, p); + addToken(JavaTokenType.J_ANNO, start, 1, new CodeSemantics()); + return super.visitAnnotation(node, null); } @Override - public Object visitModule(ModuleTree node, Object p) { + public Void visitModule(ModuleTree node, Void unused) { long start = positions.getStartPosition(ast, node); long end = positions.getEndPosition(ast, node) - 1; - addToken(JavaTokenType.J_MODULE_BEGIN, start, 6); - Object result = super.visitModule(node, p); - addToken(JavaTokenType.J_MODULE_END, end, 1); - return result; + addToken(JavaTokenType.J_MODULE_BEGIN, start, 6, CodeSemantics.createControl()); + super.visitModule(node, null); + addToken(JavaTokenType.J_MODULE_END, end, 1, CodeSemantics.createControl()); + return null; } @Override - public Object visitRequires(RequiresTree node, Object p) { + public Void visitRequires(RequiresTree node, Void unused) { long start = positions.getStartPosition(ast, node); - addToken(JavaTokenType.J_REQUIRES, start, 8); - return super.visitRequires(node, p); + addToken(JavaTokenType.J_REQUIRES, start, 8, CodeSemantics.createControl()); + return super.visitRequires(node, null); } @Override - public Object visitProvides(ProvidesTree node, Object p) { + public Void visitProvides(ProvidesTree node, Void unused) { long start = positions.getStartPosition(ast, node); - addToken(JavaTokenType.J_PROVIDES, start, 8); - return super.visitProvides(node, p); + addToken(JavaTokenType.J_PROVIDES, start, 8, CodeSemantics.createControl()); + return super.visitProvides(node, null); } @Override - public Object visitExports(ExportsTree node, Object p) { + public Void visitExports(ExportsTree node, Void unused) { long start = positions.getStartPosition(ast, node); - addToken(JavaTokenType.J_EXPORTS, start, 7); - return super.visitExports(node, p); + addToken(JavaTokenType.J_EXPORTS, start, 7, CodeSemantics.createControl()); + return super.visitExports(node, null); } @Override - public Object visitErroneous(ErroneousTree node, Object p) { + public Void visitErroneous(ErroneousTree node, Void unused) { parsingExceptions.add(new ParsingException(file, "error while visiting %s".formatted(node))); - return super.visitErroneous(node, p); + return super.visitErroneous(node, null); } @Override - public Object visitYield(YieldTree node, Object p) { + public Void visitYield(YieldTree node, Void unused) { long start = positions.getStartPosition(ast, node); long end = positions.getEndPosition(ast, node); - addToken(JavaTokenType.J_YIELD, start, end); - return super.visitYield(node, p); + addToken(JavaTokenType.J_YIELD, start, end, CodeSemantics.createControl()); + return super.visitYield(node, null); } @Override - public Object visitDefaultCaseLabel(DefaultCaseLabelTree node, Object p) { + public Void visitDefaultCaseLabel(DefaultCaseLabelTree node, Void unused) { long start = positions.getStartPosition(ast, node); long end = positions.getEndPosition(ast, node); - addToken(JavaTokenType.J_DEFAULT, start, end); - return super.visitDefaultCaseLabel(node, p); + addToken(JavaTokenType.J_DEFAULT, start, end, CodeSemantics.createControl()); + return super.visitDefaultCaseLabel(node, null); + } + + @Override + public Void visitMemberSelect(MemberSelectTree node, Void unused) { + if (node.getExpression().toString().equals("this")) { + variableRegistry.registerVariableAccess(node.getIdentifier().toString(), true); + } + variableRegistry.setIgnoreNextVariableAccess(false); // don't ignore the foo in foo.bar() + return super.visitMemberSelect(node, null); + } + + @Override + public Void visitIdentifier(IdentifierTree node, Void unused) { + variableRegistry.registerVariableAccess(node.toString(), false); + return super.visitIdentifier(node, null); } } diff --git a/languages/java/src/test/java/de/jplag/java/AbstractJavaLanguageTest.java b/languages/java/src/test/java/de/jplag/java/AbstractJavaLanguageTest.java deleted file mode 100644 index a5b02418f..000000000 --- a/languages/java/src/test/java/de/jplag/java/AbstractJavaLanguageTest.java +++ /dev/null @@ -1,54 +0,0 @@ -package de.jplag.java; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.io.File; -import java.nio.file.Path; -import java.util.List; -import java.util.Set; - -import org.junit.jupiter.api.BeforeEach; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import de.jplag.ParsingException; -import de.jplag.Token; -import de.jplag.TokenPrinter; -import de.jplag.TokenType; - -/** - * Basic test class for testing the Java language module. - */ -public abstract class AbstractJavaLanguageTest { - - private static final Path BASE_PATH = Path.of("src", "test", "resources", "java"); - private static final String LOG_MESSAGE = "Tokens of {}: {}"; - private final Logger logger = LoggerFactory.getLogger(JavaBlockTest.class); - private de.jplag.Language language; - protected File baseDirectory; - - /** - * Sets up the base directory and the language module. - */ - @BeforeEach - void setUp() { - language = new Language(); - baseDirectory = BASE_PATH.toFile(); - assertTrue(baseDirectory.exists(), "Could not find base directory!"); - } - - /** - * Parses a java file in the {@link AbstractJavaLanguageTest.baseDirectory} and returns the list of token types. - * @param fileName is the name of the file to parse. - * @return the token types. - * @throws ParsingException if parsing fails. - */ - protected List parseJavaFile(String fileName) throws ParsingException { - List parsedTokens = language.parse(Set.of(new File(baseDirectory, fileName))); - List tokenTypes = parsedTokens.stream().map(Token::getType).toList(); - logger.info(LOG_MESSAGE, fileName, tokenTypes); - logger.info(TokenPrinter.printTokens(parsedTokens, BASE_PATH.toAbsolutePath().toFile())); - return tokenTypes; - } - -} \ No newline at end of file diff --git a/languages/java/src/test/java/de/jplag/java/JavaBlockTest.java b/languages/java/src/test/java/de/jplag/java/JavaBlockTest.java deleted file mode 100644 index 57f52c704..000000000 --- a/languages/java/src/test/java/de/jplag/java/JavaBlockTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package de.jplag.java; - -import static org.junit.jupiter.api.Assertions.assertIterableEquals; - -import java.util.stream.Stream; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import de.jplag.ParsingException; - -/** - * Test cases regarding the extraction from implicit vs. explicit blocks in Java code. - */ -class JavaBlockTest extends AbstractJavaLanguageTest { - @ParameterizedTest - @MethodSource("provideClassPairs") - @DisplayName("Test pairs of classes with explicit vs. implicit blocks.") - void testJavaClassPair(String fileName1, String fileName2) throws ParsingException { - assertIterableEquals(parseJavaFile(fileName1), parseJavaFile(fileName2)); - } - - /** - * Argument source for the test case {@link testJavaClassPair(String, String)). - */ - private static Stream provideClassPairs() { - return Stream.of(Arguments.of("IfWithBraces.java", "IfWithoutBraces.java"), // just if conditions - Arguments.of("Verbose.java", "Compact.java")); // complex case with different blocks - } - -} diff --git a/languages/java/src/test/java/de/jplag/java/JavaLanguageTest.java b/languages/java/src/test/java/de/jplag/java/JavaLanguageTest.java new file mode 100644 index 000000000..51e36d7c2 --- /dev/null +++ b/languages/java/src/test/java/de/jplag/java/JavaLanguageTest.java @@ -0,0 +1,49 @@ +package de.jplag.java; + +import static de.jplag.java.JavaTokenType.*; + +import de.jplag.testutils.LanguageModuleTest; +import de.jplag.testutils.datacollector.TestDataCollector; +import de.jplag.testutils.datacollector.TestSourceIgnoredLinesCollector; + +public class JavaLanguageTest extends LanguageModuleTest { + public JavaLanguageTest() { + super(new JavaLanguage(), JavaTokenType.class); + } + + @Override + protected void collectTestData(TestDataCollector collector) { + // Test cases regarding the extraction from if and else conditions. + collector.testFile("IfElse.java", "IfIf.java", "IfElseIf.java").testSourceCoverage().testTokenSequence(J_IMPORT, J_CLASS_BEGIN, + J_METHOD_BEGIN, J_VARDEF, J_IF_BEGIN, J_THROW, J_NEWCLASS, J_IF_END, J_IF_BEGIN, J_APPLY, J_APPLY, J_IF_END, J_METHOD_END, + J_CLASS_END); + + // Test cases regarding the extraction from implicit vs. explicit blocks in Java code. + collector.testFile("IfWithBraces.java", "IfWithoutBraces.java").testSourceCoverage().testTokenSequence(J_PACKAGE, J_IMPORT, J_CLASS_BEGIN, + J_METHOD_BEGIN, J_VARDEF, J_IF_BEGIN, J_THROW, J_NEWCLASS, J_IF_END, J_IF_BEGIN, J_APPLY, J_APPLY, J_IF_END, J_IF_BEGIN, J_APPLY, + J_IF_END, J_METHOD_END, J_CLASS_END); + + collector.testFile("Verbose.java", "Compact.java").testSourceCoverage().testTokenSequence(J_PACKAGE, J_IMPORT, J_CLASS_BEGIN, J_METHOD_BEGIN, + J_VARDEF, J_VARDEF, J_IF_BEGIN, J_APPLY, J_RETURN, J_IF_END, J_VARDEF, J_LOOP_BEGIN, J_VARDEF, J_APPLY, J_ASSIGN, J_IF_BEGIN, J_APPLY, + J_APPLY, J_ASSIGN, J_IF_END, J_LOOP_END, J_IF_BEGIN, J_APPLY, J_ASSIGN, J_IF_END, J_IF_BEGIN, J_APPLY, J_APPLY, J_ASSIGN, J_IF_END, + J_RETURN, J_METHOD_END, J_CLASS_END); + + // Test difference between try block and try-with-resource block. + collector.testFile("Try.java", "TryWithResource.java").testSourceCoverage().testTokenSequence(J_PACKAGE, J_IMPORT, J_IMPORT, J_IMPORT, + J_CLASS_BEGIN, J_METHOD_BEGIN, J_VARDEF, J_APPLY, J_NEWCLASS, J_METHOD_END, J_METHOD_BEGIN, J_VARDEF, J_VARDEF, J_TRY_BEGIN, J_VARDEF, + J_ASSIGN, J_NEWCLASS, J_NEWCLASS, J_LOOP_BEGIN, J_APPLY, J_APPLY, J_APPLY, J_LOOP_END, J_CATCH_BEGIN, J_VARDEF, J_APPLY, J_CATCH_END, + J_FINALLY_BEGIN, J_IF_BEGIN, J_APPLY, J_IF_END, J_FINALLY_END, J_TRY_END, J_METHOD_END, J_CLASS_END); + + collector.testFile("CLI.java").testSourceCoverage().testContainedTokens(J_TRY_END, J_IMPORT, J_VARDEF, J_LOOP_BEGIN, J_ARRAY_INIT_BEGIN, + J_IF_BEGIN, J_CATCH_END, J_COND, J_ARRAY_INIT_END, J_METHOD_BEGIN, J_TRY_BEGIN, J_CLASS_END, J_RETURN, J_ASSIGN, J_METHOD_END, + J_IF_END, J_CLASS_BEGIN, J_NEWARRAY, J_PACKAGE, J_APPLY, J_LOOP_END, J_THROW, J_NEWCLASS, J_CATCH_BEGIN); + } + + @Override + protected void configureIgnoredLines(TestSourceIgnoredLinesCollector collector) { + collector.ignoreLinesByPrefix("//"); + collector.ignoreMultipleLines("/*", "*/"); + collector.ignoreLinesByPrefix("})"); + collector.ignoreByCondition(line -> line.contains("else") && !line.contains("if")); + } +} diff --git a/languages/java/src/test/java/de/jplag/java/JavaTryTest.java b/languages/java/src/test/java/de/jplag/java/JavaTryTest.java deleted file mode 100644 index c5ee683d9..000000000 --- a/languages/java/src/test/java/de/jplag/java/JavaTryTest.java +++ /dev/null @@ -1,20 +0,0 @@ - -package de.jplag.java; - -import static org.junit.jupiter.api.Assertions.assertIterableEquals; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import de.jplag.ParsingException; - -/** - * Test cases regarding the extraction from try vs. try with resource. - */ -class JavaTryTest extends AbstractJavaLanguageTest { - @Test - @DisplayName("Test difference between try block and try-with-resource block.") - void testJavaClassPair() throws ParsingException { - assertIterableEquals(parseJavaFile("Try.java"), parseJavaFile("TryWithResource.java")); - } -} diff --git a/languages/java/src/test/resources/de/jplag/java/CLI.java b/languages/java/src/test/resources/de/jplag/java/CLI.java new file mode 100644 index 000000000..a019fe54c --- /dev/null +++ b/languages/java/src/test/resources/de/jplag/java/CLI.java @@ -0,0 +1,220 @@ +package de.jplag.cli; + +import static picocli.CommandLine.Model.UsageMessageSpec.SECTION_KEY_FOOTER; +import static picocli.CommandLine.Model.UsageMessageSpec.SECTION_KEY_OPTION_LIST; + +import java.io.File; +import java.security.SecureRandom; +import java.util.HashSet; +import java.util.List; +import java.util.Random; +import java.util.Set; +import java.util.stream.Collectors; + +import org.slf4j.ILoggerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import de.jplag.JPlag; +import de.jplag.JPlagResult; +import de.jplag.Language; +import de.jplag.cli.logger.CollectedLoggerFactory; +import de.jplag.clustering.ClusteringOptions; +import de.jplag.clustering.Preprocessing; +import de.jplag.exceptions.ExitException; +import de.jplag.options.JPlagOptions; +import de.jplag.options.LanguageOption; +import de.jplag.options.LanguageOptions; +import de.jplag.reporting.reportobject.ReportObjectFactory; + +import picocli.CommandLine; +import picocli.CommandLine.Model.CommandSpec; +import picocli.CommandLine.Model.OptionSpec; +import picocli.CommandLine.ParseResult; + +/** + * Command line interface class, allows using via command line. + * + * @see CLI#main(String[]) + */ +public final class CLI { + + private static final Logger logger = LoggerFactory.getLogger(CLI.class); + + private static final Random RANDOM = new SecureRandom(); + + private static final String CREDITS = "Created by IPD Tichy, Guido Malpohl, and others. JPlag logo designed by Sandro Koch. Currently maintained by Sebastian Hahner and Timur Saglam."; + + private static final String[] DESCRIPTIONS = {"Detecting Software Plagiarism", "Software-Archaeological Playground", "Since 1996", "Scientifically Published", "Maintained by SDQ", "RIP Structure and Table", "What else?", "You have been warned!", "Since Java 1.0", "More Abstract than Tree", "Students Nightmare", "No, changing variable names does not work", "The tech is out there!", "Developed by plagiarism experts."}; + + private final CommandLine commandLine; + private final CliOptions options; + + private static final String IMPOSSIBLE_EXCEPTION = "This should not have happened." + " Please create an issue on github (https://github.com/jplag/JPlag/issues) with the entire output."; + + /** + * Main class for using JPlag via the CLI. + * + * @param args are the CLI arguments that will be passed to JPlag. + */ + public static void main(String[] args) { + try { + logger.debug("Your version of JPlag is {}", JPlag.JPLAG_VERSION); + + CLI cli = new CLI(); + + ParseResult parseResult = cli.parseOptions(args); + + if (!parseResult.isUsageHelpRequested() && !(parseResult.subcommand() != null && parseResult.subcommand().isUsageHelpRequested())) { + JPlagOptions options = cli.buildOptionsFromArguments(parseResult); + JPlagResult result = JPlag.run(options); + ReportObjectFactory reportObjectFactory = new ReportObjectFactory(); + reportObjectFactory.createAndSaveReport(result, cli.getResultFolder()); + } + } catch (ExitException exception) { + logger.error(exception.getMessage()); // do not pass exception here to keep log clean + finalizeLogger(); + System.exit(1); + } + } + + /** + * Creates a new instance + */ + public CLI() { + this.options = new CliOptions(); + this.commandLine = new CommandLine(options); + + this.commandLine.getHelpSectionMap().put(SECTION_KEY_OPTION_LIST, help -> help.optionList().lines().map(it -> { + if (it.startsWith(" -")) { + return " " + it; + } else { + return it; + } + }).collect(Collectors.joining(System.lineSeparator()))); + + buildSubcommands().forEach(commandLine::addSubcommand); + + this.commandLine.getHelpSectionMap().put(SECTION_KEY_FOOTER, help -> generateDescription()); + this.commandLine.setAllowSubcommandsAsOptionParameters(true); + } + + private List buildSubcommands() { + return LanguageLoader.getAllAvailableLanguages().values().stream().map(language -> { + CommandSpec command = CommandSpec.create().name(language.getIdentifier()); + + for (LanguageOption option : language.getOptions().getOptionsAsList()) { + command.addOption(OptionSpec.builder(option.getNameAsUnixParameter()).type(option.getType().getJavaType()) + .description(option.getDescription()).build()); + } + command.mixinStandardHelpOptions(true); + command.addPositional( + CommandLine.Model.PositionalParamSpec.builder().type(List.class).auxiliaryTypes(File.class).hidden(true).required(false).build()); + + return command; + }).toList(); + } + + /** + * Parses the options from the given command line arguments. Also prints help pages when requested. + * + * @param args The command line arguments + * @return the parse result generated by picocli + */ + public ParseResult parseOptions(String... args) throws CliException { + try { + ParseResult result = commandLine.parseArgs(args); + if (result.isUsageHelpRequested() || (result.subcommand() != null && result.subcommand().isUsageHelpRequested())) { + commandLine.getExecutionStrategy().execute(result); + } + return result; + } catch (CommandLine.PicocliException e) { + throw new CliException("Error during parsing", e); + } + } + + private static void finalizeLogger() { + ILoggerFactory factory = LoggerFactory.getILoggerFactory(); + if (!(factory instanceof CollectedLoggerFactory collectedLoggerFactory)) { + return; + } + collectedLoggerFactory.finalizeInstances(); + } + + /** + * Builds an options instance from parsed options. + * + * @return the newly built options + */ + public JPlagOptions buildOptionsFromArguments(ParseResult parseResult) throws CliException { + Set submissionDirectories = new HashSet<>(List.of(this.options.rootDirectory)); + Set oldSubmissionDirectories = Set.of(this.options.oldDirectories); + List suffixes = List.of(this.options.advanced.suffixes); + submissionDirectories.addAll(List.of(this.options.newDirectories)); + + if (parseResult.subcommand() != null && parseResult.subcommand().hasMatchedPositional(0)) { + submissionDirectories.addAll(parseResult.subcommand().matchedPositional(0).getValue()); + } + + ClusteringOptions clusteringOptions = getClusteringOptions(this.options); + + JPlagOptions jPlagOptions = new JPlagOptions(loadLanguage(parseResult), this.options.minTokenMatch, submissionDirectories, oldSubmissionDirectories, null, this.options.advanced.subdirectory, suffixes, this.options.advanced.exclusionFileName, JPlagOptions.DEFAULT_SIMILARITY_METRIC, this.options.advanced.similarityThreshold, this.options.shownComparisons, clusteringOptions, this.options.advanced.debug); + + String baseCodePath = this.options.baseCode; + File baseCodeDirectory = baseCodePath == null ? null : new File(baseCodePath); + if (baseCodeDirectory == null || baseCodeDirectory.exists()) { + return jPlagOptions.withBaseCodeSubmissionDirectory(baseCodeDirectory); + } else { + logger.warn("Using legacy partial base code API. Please migrate to new full path base code API."); + return jPlagOptions.withBaseCodeSubmissionName(baseCodePath); + } + } + + private Language loadLanguage(ParseResult result) throws CliException { + if (result.subcommand() != null) { + ParseResult subcommandResult = result.subcommand(); + Language language = LanguageLoader.getLanguage(subcommandResult.commandSpec().name()) + .orElseThrow(() -> new CliException(IMPOSSIBLE_EXCEPTION)); + LanguageOptions languageOptions = language.getOptions(); + languageOptions.getOptionsAsList().forEach(option -> { + if (subcommandResult.hasMatchedOption(option.getNameAsUnixParameter())) { + option.setValue(subcommandResult.matchedOptionValue(option.getNameAsUnixParameter(), null)); + } + }); + return language; + } else { + return this.options.language; + } + } + + private static ClusteringOptions getClusteringOptions(CliOptions options) { + ClusteringOptions clusteringOptions = new ClusteringOptions().withEnabled(!options.clustering.disable).withAlgorithm(options.clustering.enabled.algorithm).withSimilarityMetric(options.clustering.enabled.metric).withSpectralKernelBandwidth(options.clusterSpectralBandwidth).withSpectralGaussianProcessVariance(options.clusterSpectralNoise).withSpectralMinRuns(options.clusterSpectralMinRuns).withSpectralMaxRuns(options.clusterSpectralMaxRuns).withSpectralMaxKMeansIterationPerRun(options.clusterSpectralKMeansIterations).withAgglomerativeThreshold(options.clusterAgglomerativeThreshold).withAgglomerativeInterClusterSimilarity(options.clusterAgglomerativeInterClusterSimilarity); + + if (options.clusterPreprocessingNone) { + clusteringOptions = clusteringOptions.withPreprocessor(Preprocessing.NONE); + } + + if (options.clusterPreprocessingCdf) { + clusteringOptions = clusteringOptions.withPreprocessor(Preprocessing.CUMULATIVE_DISTRIBUTION_FUNCTION); + } + + if (options.clusterPreprocessingPercentile != 0) { + clusteringOptions = clusteringOptions.withPreprocessor(Preprocessing.PERCENTILE).withPreprocessorPercentile(options.clusterPreprocessingPercentile); + } + + if (options.clusterPreprocessingThreshold != 0) { + clusteringOptions = clusteringOptions.withPreprocessor(Preprocessing.THRESHOLD).withPreprocessorThreshold(options.clusterPreprocessingThreshold); + } + + return clusteringOptions; + } + + private String generateDescription() { + var randomDescription = DESCRIPTIONS[RANDOM.nextInt(DESCRIPTIONS.length)]; + return String.format("JPlag - %s%n%n%s", randomDescription, CREDITS); + } + + public String getResultFolder() { + return this.options.resultFolder; + } +} diff --git a/languages/java/src/test/resources/java/Compact.java b/languages/java/src/test/resources/de/jplag/java/Compact.java similarity index 100% rename from languages/java/src/test/resources/java/Compact.java rename to languages/java/src/test/resources/de/jplag/java/Compact.java diff --git a/languages/java/src/test/resources/de/jplag/java/IfElse.java b/languages/java/src/test/resources/de/jplag/java/IfElse.java new file mode 100644 index 000000000..1b84c568d --- /dev/null +++ b/languages/java/src/test/resources/de/jplag/java/IfElse.java @@ -0,0 +1,11 @@ +import java.util.Arrays; + +public class IfElse2 { + public static void main(String[] args) { + if (args == null) { + throw new IllegalArgumentException(); + } else { + System.out.println(Arrays.toString(args)); + } + } +} diff --git a/languages/java/src/test/resources/de/jplag/java/IfElseIf.java b/languages/java/src/test/resources/de/jplag/java/IfElseIf.java new file mode 100644 index 000000000..35d8ec093 --- /dev/null +++ b/languages/java/src/test/resources/de/jplag/java/IfElseIf.java @@ -0,0 +1,11 @@ +import java.util.Arrays; + +public class IfElse2 { + public static void main(String[] args) { + if (args == null) { + throw new IllegalArgumentException(); + } else if (args.length > 1) { + System.out.println(Arrays.toString(args)); + } + } +} diff --git a/languages/java/src/test/resources/de/jplag/java/IfIf.java b/languages/java/src/test/resources/de/jplag/java/IfIf.java new file mode 100644 index 000000000..331da451e --- /dev/null +++ b/languages/java/src/test/resources/de/jplag/java/IfIf.java @@ -0,0 +1,12 @@ +import java.util.Arrays; + +public class IfElse1 { + public static void main(String[] args) { + if (args == null) { + throw new IllegalArgumentException(); + } + if (args.length > 1) { + System.out.println(Arrays.toString(args)); + } + } +} diff --git a/languages/java/src/test/resources/java/IfWithBraces.java b/languages/java/src/test/resources/de/jplag/java/IfWithBraces.java similarity index 100% rename from languages/java/src/test/resources/java/IfWithBraces.java rename to languages/java/src/test/resources/de/jplag/java/IfWithBraces.java diff --git a/languages/java/src/test/resources/java/IfWithoutBraces.java b/languages/java/src/test/resources/de/jplag/java/IfWithoutBraces.java similarity index 100% rename from languages/java/src/test/resources/java/IfWithoutBraces.java rename to languages/java/src/test/resources/de/jplag/java/IfWithoutBraces.java diff --git a/languages/java/src/test/resources/java/Try.java b/languages/java/src/test/resources/de/jplag/java/Try.java similarity index 100% rename from languages/java/src/test/resources/java/Try.java rename to languages/java/src/test/resources/de/jplag/java/Try.java diff --git a/languages/java/src/test/resources/java/TryWithResource.java b/languages/java/src/test/resources/de/jplag/java/TryWithResource.java similarity index 100% rename from languages/java/src/test/resources/java/TryWithResource.java rename to languages/java/src/test/resources/de/jplag/java/TryWithResource.java diff --git a/languages/java/src/test/resources/java/Verbose.java b/languages/java/src/test/resources/de/jplag/java/Verbose.java similarity index 100% rename from languages/java/src/test/resources/java/Verbose.java rename to languages/java/src/test/resources/de/jplag/java/Verbose.java diff --git a/languages/kotlin/README.md b/languages/kotlin/README.md index cbd229da0..7c19d7200 100644 --- a/languages/kotlin/README.md +++ b/languages/kotlin/README.md @@ -20,7 +20,7 @@ More syntactic elements of Kotlin may turn out to be helpful to include in the f ### Usage -To use the Kotlin module, add the `-l kotlin` flag in the CLI, or use a `JPlagOption` object with `new de.jplag.kotlin.Language()` as `language` in the Java API as described in the usage information in the [readme of the main project](https://github.com/jplag/JPlag#usage) and [in the wiki](https://github.com/jplag/JPlag/wiki/1.-How-to-Use-JPlag). +To use the Kotlin module, add the `-l kotlin` flag in the CLI, or use a `JPlagOption` object with `new de.jplag.kotlin.KotlinLanguage()` as `language` in the Java API as described in the usage information in the [readme of the main project](https://github.com/jplag/JPlag#usage) and [in the wiki](https://github.com/jplag/JPlag/wiki/1.-How-to-Use-JPlag).
diff --git a/languages/kotlin/pom.xml b/languages/kotlin/pom.xml index 76154d39a..dbbe1f6f8 100644 --- a/languages/kotlin/pom.xml +++ b/languages/kotlin/pom.xml @@ -14,6 +14,11 @@ org.antlr antlr4-runtime + + de.jplag + language-antlr-utils + 4.4.0-SNAPSHOT + diff --git a/languages/kotlin/src/main/java/de/jplag/kotlin/JPlagKotlinListener.java b/languages/kotlin/src/main/java/de/jplag/kotlin/JPlagKotlinListener.java deleted file mode 100644 index 888a4e748..000000000 --- a/languages/kotlin/src/main/java/de/jplag/kotlin/JPlagKotlinListener.java +++ /dev/null @@ -1,423 +0,0 @@ -package de.jplag.kotlin; - -import static de.jplag.kotlin.KotlinTokenType.ASSIGNMENT; -import static de.jplag.kotlin.KotlinTokenType.BREAK; -import static de.jplag.kotlin.KotlinTokenType.CATCH; -import static de.jplag.kotlin.KotlinTokenType.CATCH_BODY_END; -import static de.jplag.kotlin.KotlinTokenType.CATCH_BODY_START; -import static de.jplag.kotlin.KotlinTokenType.CLASS_BODY_BEGIN; -import static de.jplag.kotlin.KotlinTokenType.CLASS_BODY_END; -import static de.jplag.kotlin.KotlinTokenType.CLASS_DECLARATION; -import static de.jplag.kotlin.KotlinTokenType.COMPANION_DECLARATION; -import static de.jplag.kotlin.KotlinTokenType.CONSTRUCTOR; -import static de.jplag.kotlin.KotlinTokenType.CONTINUE; -import static de.jplag.kotlin.KotlinTokenType.CONTROL_STRUCTURE_BODY_END; -import static de.jplag.kotlin.KotlinTokenType.CONTROL_STRUCTURE_BODY_START; -import static de.jplag.kotlin.KotlinTokenType.CREATE_OBJECT; -import static de.jplag.kotlin.KotlinTokenType.DO_WHILE_EXPRESSION_END; -import static de.jplag.kotlin.KotlinTokenType.DO_WHILE_EXPRESSION_START; -import static de.jplag.kotlin.KotlinTokenType.ENUM_CLASS_BODY_BEGIN; -import static de.jplag.kotlin.KotlinTokenType.ENUM_CLASS_BODY_END; -import static de.jplag.kotlin.KotlinTokenType.ENUM_ENTRY; -import static de.jplag.kotlin.KotlinTokenType.FINALLY; -import static de.jplag.kotlin.KotlinTokenType.FINALLY_BODY_END; -import static de.jplag.kotlin.KotlinTokenType.FINALLY_BODY_START; -import static de.jplag.kotlin.KotlinTokenType.FOR_EXPRESSION_BEGIN; -import static de.jplag.kotlin.KotlinTokenType.FOR_EXPRESSION_END; -import static de.jplag.kotlin.KotlinTokenType.FUNCTION; -import static de.jplag.kotlin.KotlinTokenType.FUNCTION_BODY_BEGIN; -import static de.jplag.kotlin.KotlinTokenType.FUNCTION_BODY_END; -import static de.jplag.kotlin.KotlinTokenType.FUNCTION_INVOCATION; -import static de.jplag.kotlin.KotlinTokenType.FUNCTION_LITERAL_BEGIN; -import static de.jplag.kotlin.KotlinTokenType.FUNCTION_LITERAL_END; -import static de.jplag.kotlin.KotlinTokenType.FUNCTION_PARAMETER; -import static de.jplag.kotlin.KotlinTokenType.GETTER; -import static de.jplag.kotlin.KotlinTokenType.IF_EXPRESSION_END; -import static de.jplag.kotlin.KotlinTokenType.IF_EXPRESSION_START; -import static de.jplag.kotlin.KotlinTokenType.IMPORT; -import static de.jplag.kotlin.KotlinTokenType.INITIALIZER; -import static de.jplag.kotlin.KotlinTokenType.INITIALIZER_BODY_END; -import static de.jplag.kotlin.KotlinTokenType.INITIALIZER_BODY_START; -import static de.jplag.kotlin.KotlinTokenType.OBJECT_DECLARATION; -import static de.jplag.kotlin.KotlinTokenType.PACKAGE; -import static de.jplag.kotlin.KotlinTokenType.PROPERTY_DECLARATION; -import static de.jplag.kotlin.KotlinTokenType.RETURN; -import static de.jplag.kotlin.KotlinTokenType.SETTER; -import static de.jplag.kotlin.KotlinTokenType.THROW; -import static de.jplag.kotlin.KotlinTokenType.TRY_BODY_END; -import static de.jplag.kotlin.KotlinTokenType.TRY_BODY_START; -import static de.jplag.kotlin.KotlinTokenType.TRY_EXPRESSION; -import static de.jplag.kotlin.KotlinTokenType.TYPE_PARAMETER; -import static de.jplag.kotlin.KotlinTokenType.VARIABLE_DECLARATION; -import static de.jplag.kotlin.KotlinTokenType.WHEN_CONDITION; -import static de.jplag.kotlin.KotlinTokenType.WHEN_EXPRESSION_END; -import static de.jplag.kotlin.KotlinTokenType.WHEN_EXPRESSION_START; -import static de.jplag.kotlin.KotlinTokenType.WHILE_EXPRESSION_END; -import static de.jplag.kotlin.KotlinTokenType.WHILE_EXPRESSION_START; - -import java.util.Optional; - -import org.antlr.v4.runtime.Token; -import org.antlr.v4.runtime.tree.TerminalNode; - -import de.jplag.kotlin.grammar.KotlinParser; -import de.jplag.kotlin.grammar.KotlinParserBaseListener; - -public class JPlagKotlinListener extends KotlinParserBaseListener { - private final KotlinParserAdapter parserAdapter; - - public JPlagKotlinListener(KotlinParserAdapter parserAdapter) { - this.parserAdapter = parserAdapter; - } - - /** - * Passes a token of the given tokenType to the parserAdapter, representing the grammar's token given by token. - * @param tokenType the custom token type that occurred. - * @param token the corresponding grammar's token - */ - private void transformToken(KotlinTokenType tokenType, Token token) { - parserAdapter.addToken(tokenType, token.getLine(), token.getCharPositionInLine() + 1, token.getText().length()); - } - - /** - * Passes a token of the given tokenType to the parserAdapter, representing the current grammatical context given by - * start and end. - * @param tokenType the custom token type that occurred. - * @param start the first Token of the context - * @param end the last Token of the context - */ - private void transformToken(KotlinTokenType tokenType, Token start, Token end) { - parserAdapter.addToken(tokenType, start.getLine(), start.getCharPositionInLine() + 1, end.getStopIndex() - start.getStartIndex() + 1); - } - - @Override - public void enterPackageHeader(KotlinParser.PackageHeaderContext context) { - transformToken(PACKAGE, context.getStart(), context.getStop()); - super.enterPackageHeader(context); - } - - @Override - public void enterImportHeader(KotlinParser.ImportHeaderContext context) { - transformToken(IMPORT, context.getStart(), context.getStop()); - super.enterImportHeader(context); - } - - @Override - public void enterClassDeclaration(KotlinParser.ClassDeclarationContext context) { - transformToken(CLASS_DECLARATION, context.getStart()); - super.enterClassDeclaration(context); - } - - @Override - public void enterObjectDeclaration(KotlinParser.ObjectDeclarationContext context) { - transformToken(OBJECT_DECLARATION, context.getStart(), context.getStop()); - super.enterObjectDeclaration(context); - } - - @Override - public void enterCompanionObject(KotlinParser.CompanionObjectContext context) { - transformToken(COMPANION_DECLARATION, context.getStart()); - super.enterCompanionObject(context); - } - - @Override - public void enterTypeParameter(KotlinParser.TypeParameterContext context) { - transformToken(TYPE_PARAMETER, context.getStart(), context.getStop()); - super.enterTypeParameter(context); - } - - @Override - public void enterPrimaryConstructor(KotlinParser.PrimaryConstructorContext context) { - transformToken(CONSTRUCTOR, context.getStart(), context.getStop()); - super.enterPrimaryConstructor(context); - } - - @Override - public void enterClassParameter(KotlinParser.ClassParameterContext context) { - transformToken(PROPERTY_DECLARATION, context.getStart(), context.getStop()); - super.enterClassParameter(context); - } - - @Override - public void enterClassBody(KotlinParser.ClassBodyContext context) { - transformToken(CLASS_BODY_BEGIN, context.getStart()); - super.enterClassBody(context); - } - - @Override - public void exitClassBody(KotlinParser.ClassBodyContext context) { - transformToken(CLASS_BODY_END, context.getStop()); - super.exitClassBody(context); - } - - @Override - public void enterEnumClassBody(KotlinParser.EnumClassBodyContext context) { - transformToken(ENUM_CLASS_BODY_BEGIN, context.getStart()); - super.enterEnumClassBody(context); - } - - @Override - public void exitEnumClassBody(KotlinParser.EnumClassBodyContext context) { - transformToken(ENUM_CLASS_BODY_END, context.getStop()); - super.exitEnumClassBody(context); - } - - @Override - public void enterEnumEntry(KotlinParser.EnumEntryContext context) { - transformToken(ENUM_ENTRY, context.getStart()); - super.enterEnumEntry(context); - } - - @Override - public void enterSecondaryConstructor(KotlinParser.SecondaryConstructorContext context) { - transformToken(CONSTRUCTOR, context.getStart(), context.getStop()); - super.enterSecondaryConstructor(context); - } - - @Override - public void enterPropertyDeclaration(KotlinParser.PropertyDeclarationContext context) { - transformToken(PROPERTY_DECLARATION, context.getStart()); - super.enterPropertyDeclaration(context); - } - - @Override - public void enterAnonymousInitializer(KotlinParser.AnonymousInitializerContext context) { - transformToken(INITIALIZER, context.getStart()); - super.enterAnonymousInitializer(context); - } - - @Override - public void enterInitBlock(KotlinParser.InitBlockContext context) { - transformToken(INITIALIZER_BODY_START, context.getStart()); - super.enterInitBlock(context); - } - - @Override - public void exitInitBlock(KotlinParser.InitBlockContext context) { - transformToken(INITIALIZER_BODY_END, context.getStop()); - super.exitInitBlock(context); - } - - @Override - public void enterFunctionDeclaration(KotlinParser.FunctionDeclarationContext context) { - transformToken(FUNCTION, context.getStart()); - super.enterFunctionDeclaration(context); - } - - @Override - public void enterGetter(KotlinParser.GetterContext context) { - transformToken(GETTER, context.getStart()); - super.enterGetter(context); - } - - @Override - public void enterSetter(KotlinParser.SetterContext context) { - transformToken(SETTER, context.getStart()); - super.enterSetter(context); - } - - @Override - public void enterFunctionValueParameter(KotlinParser.FunctionValueParameterContext context) { - transformToken(FUNCTION_PARAMETER, context.getStart(), context.getStop()); - super.enterFunctionValueParameter(context); - } - - @Override - public void enterFunctionBody(KotlinParser.FunctionBodyContext context) { - transformToken(FUNCTION_BODY_BEGIN, context.getStart()); - super.enterFunctionBody(context); - } - - @Override - public void exitFunctionBody(KotlinParser.FunctionBodyContext context) { - transformToken(FUNCTION_BODY_END, context.getStop()); - super.exitFunctionBody(context); - } - - @Override - public void enterFunctionLiteral(KotlinParser.FunctionLiteralContext context) { - transformToken(FUNCTION_LITERAL_BEGIN, context.getStart()); - super.enterFunctionLiteral(context); - } - - @Override - public void exitFunctionLiteral(KotlinParser.FunctionLiteralContext context) { - transformToken(FUNCTION_LITERAL_END, context.getStop()); - super.exitFunctionLiteral(context); - } - - @Override - public void enterForExpression(KotlinParser.ForExpressionContext context) { - transformToken(FOR_EXPRESSION_BEGIN, context.getStart()); - super.enterForExpression(context); - } - - @Override - public void exitForExpression(KotlinParser.ForExpressionContext context) { - transformToken(FOR_EXPRESSION_END, context.getStop()); - super.exitForExpression(context); - } - - @Override - public void enterIfExpression(KotlinParser.IfExpressionContext context) { - transformToken(IF_EXPRESSION_START, context.getStart()); - super.enterIfExpression(context); - } - - @Override - public void exitIfExpression(KotlinParser.IfExpressionContext context) { - transformToken(IF_EXPRESSION_END, context.getStop()); - super.exitIfExpression(context); - } - - @Override - public void enterWhileExpression(KotlinParser.WhileExpressionContext context) { - transformToken(WHILE_EXPRESSION_START, context.getStart()); - super.enterWhileExpression(context); - } - - @Override - public void exitWhileExpression(KotlinParser.WhileExpressionContext context) { - transformToken(WHILE_EXPRESSION_END, context.getStop()); - super.exitWhileExpression(context); - } - - @Override - public void enterDoWhileExpression(KotlinParser.DoWhileExpressionContext context) { - transformToken(DO_WHILE_EXPRESSION_START, context.getStart()); - super.enterDoWhileExpression(context); - } - - @Override - public void exitDoWhileExpression(KotlinParser.DoWhileExpressionContext context) { - transformToken(DO_WHILE_EXPRESSION_END, context.getStop()); - super.exitDoWhileExpression(context); - } - - @Override - public void enterTryExpression(KotlinParser.TryExpressionContext context) { - transformToken(TRY_EXPRESSION, context.getStart()); - super.enterTryExpression(context); - } - - @Override - public void enterTryBody(KotlinParser.TryBodyContext ctx) { - transformToken(TRY_BODY_START, ctx.getStart()); - super.enterTryBody(ctx); - } - - @Override - public void exitTryBody(KotlinParser.TryBodyContext ctx) { - transformToken(TRY_BODY_END, ctx.getStop()); - super.exitTryBody(ctx); - } - - @Override - public void enterCatchStatement(KotlinParser.CatchStatementContext context) { - transformToken(CATCH, context.getStart()); - super.enterCatchStatement(context); - } - - @Override - public void enterCatchBody(KotlinParser.CatchBodyContext context) { - transformToken(CATCH_BODY_START, context.getStart()); - super.enterCatchBody(context); - } - - @Override - public void exitCatchBody(KotlinParser.CatchBodyContext context) { - transformToken(CATCH_BODY_END, context.getStop()); - super.exitCatchBody(context); - } - - @Override - public void enterFinallyStatement(KotlinParser.FinallyStatementContext context) { - transformToken(FINALLY, context.getStart()); - super.enterFinallyStatement(context); - } - - @Override - public void enterFinallyBody(KotlinParser.FinallyBodyContext context) { - transformToken(FINALLY_BODY_START, context.getStart()); - super.enterFinallyBody(context); - } - - @Override - public void exitFinallyBody(KotlinParser.FinallyBodyContext context) { - transformToken(FINALLY_BODY_END, context.getStop()); - super.exitFinallyBody(context); - } - - @Override - public void enterWhenExpression(KotlinParser.WhenExpressionContext context) { - transformToken(WHEN_EXPRESSION_START, context.getStart()); - super.enterWhenExpression(context); - } - - @Override - public void exitWhenExpression(KotlinParser.WhenExpressionContext context) { - transformToken(WHEN_EXPRESSION_END, context.getStop()); - super.exitWhenExpression(context); - } - - @Override - public void enterWhenCondition(KotlinParser.WhenConditionContext context) { - transformToken(WHEN_CONDITION, context.getStart(), context.getStop()); - super.enterWhenCondition(context); - } - - @Override - public void enterControlStructureBody(KotlinParser.ControlStructureBodyContext context) { - transformToken(CONTROL_STRUCTURE_BODY_START, context.getStart()); - super.enterControlStructureBody(context); - } - - @Override - public void exitControlStructureBody(KotlinParser.ControlStructureBodyContext context) { - transformToken(CONTROL_STRUCTURE_BODY_END, context.getStop()); - super.exitControlStructureBody(context); - } - - @Override - public void enterVariableDeclaration(KotlinParser.VariableDeclarationContext context) { - transformToken(VARIABLE_DECLARATION, context.getStart()); - super.enterVariableDeclaration(context); - } - - @Override - public void enterConstructorInvocation(KotlinParser.ConstructorInvocationContext context) { - transformToken(CREATE_OBJECT, context.getStart(), context.getStop()); - super.enterConstructorInvocation(context); - } - - @Override - public void enterCallSuffix(KotlinParser.CallSuffixContext context) { - transformToken(FUNCTION_INVOCATION, context.getStart(), context.getStop()); - super.enterCallSuffix(context); - } - - @Override - public void enterAssignmentOperator(KotlinParser.AssignmentOperatorContext context) { - transformToken(ASSIGNMENT, context.getStart()); - super.enterAssignmentOperator(context); - } - - @Override - public void visitTerminal(TerminalNode node) { - Token token = node.getSymbol(); - String tokenText = token.getText(); - if (tokenText.contains("@")) { - tokenText = tokenText.substring(0, tokenText.indexOf("@")); - } - Optional type = switch (tokenText) { - case "throw" -> Optional.of(THROW); - case "return" -> Optional.of(RETURN); - case "continue" -> Optional.of(CONTINUE); - case "break" -> Optional.of(BREAK); - default -> Optional.empty(); - }; - - type.ifPresent(tokenType -> transformToken(tokenType, token)); - } - -} diff --git a/languages/kotlin/src/main/java/de/jplag/kotlin/Language.java b/languages/kotlin/src/main/java/de/jplag/kotlin/KotlinLanguage.java similarity index 63% rename from languages/kotlin/src/main/java/de/jplag/kotlin/Language.java rename to languages/kotlin/src/main/java/de/jplag/kotlin/KotlinLanguage.java index cc294cf2a..487effaa2 100644 --- a/languages/kotlin/src/main/java/de/jplag/kotlin/Language.java +++ b/languages/kotlin/src/main/java/de/jplag/kotlin/KotlinLanguage.java @@ -1,28 +1,22 @@ package de.jplag.kotlin; -import java.io.File; -import java.util.List; -import java.util.Set; - import org.kohsuke.MetaInfServices; -import de.jplag.ParsingException; -import de.jplag.Token; +import de.jplag.antlr.AbstractAntlrLanguage; /** * This represents the Kotlin language as a language supported by JPlag. */ @MetaInfServices(de.jplag.Language.class) -public class Language implements de.jplag.Language { +public class KotlinLanguage extends AbstractAntlrLanguage { private static final String NAME = "Kotlin Parser"; private static final String IDENTIFIER = "kotlin"; private static final int DEFAULT_MIN_TOKEN_MATCH = 8; private static final String[] FILE_EXTENSIONS = {".kt"}; - private final KotlinParserAdapter parserAdapter; - public Language() { - this.parserAdapter = new KotlinParserAdapter(); + public KotlinLanguage() { + super(new KotlinParserAdapter()); } @Override @@ -44,9 +38,4 @@ public String getIdentifier() { public int minimumTokenMatch() { return DEFAULT_MIN_TOKEN_MATCH; } - - @Override - public List parse(Set files) throws ParsingException { - return parserAdapter.parse(files); - } } diff --git a/languages/kotlin/src/main/java/de/jplag/kotlin/KotlinListener.java b/languages/kotlin/src/main/java/de/jplag/kotlin/KotlinListener.java new file mode 100644 index 000000000..19a475ffa --- /dev/null +++ b/languages/kotlin/src/main/java/de/jplag/kotlin/KotlinListener.java @@ -0,0 +1,147 @@ +package de.jplag.kotlin; + +import static de.jplag.kotlin.KotlinTokenType.ASSIGNMENT; +import static de.jplag.kotlin.KotlinTokenType.BREAK; +import static de.jplag.kotlin.KotlinTokenType.CATCH; +import static de.jplag.kotlin.KotlinTokenType.CATCH_BODY_END; +import static de.jplag.kotlin.KotlinTokenType.CATCH_BODY_START; +import static de.jplag.kotlin.KotlinTokenType.CLASS_BODY_BEGIN; +import static de.jplag.kotlin.KotlinTokenType.CLASS_BODY_END; +import static de.jplag.kotlin.KotlinTokenType.CLASS_DECLARATION; +import static de.jplag.kotlin.KotlinTokenType.COMPANION_DECLARATION; +import static de.jplag.kotlin.KotlinTokenType.CONSTRUCTOR; +import static de.jplag.kotlin.KotlinTokenType.CONTINUE; +import static de.jplag.kotlin.KotlinTokenType.CONTROL_STRUCTURE_BODY_END; +import static de.jplag.kotlin.KotlinTokenType.CONTROL_STRUCTURE_BODY_START; +import static de.jplag.kotlin.KotlinTokenType.CREATE_OBJECT; +import static de.jplag.kotlin.KotlinTokenType.DO_WHILE_EXPRESSION_END; +import static de.jplag.kotlin.KotlinTokenType.DO_WHILE_EXPRESSION_START; +import static de.jplag.kotlin.KotlinTokenType.ENUM_CLASS_BODY_BEGIN; +import static de.jplag.kotlin.KotlinTokenType.ENUM_CLASS_BODY_END; +import static de.jplag.kotlin.KotlinTokenType.ENUM_ENTRY; +import static de.jplag.kotlin.KotlinTokenType.FINALLY; +import static de.jplag.kotlin.KotlinTokenType.FINALLY_BODY_END; +import static de.jplag.kotlin.KotlinTokenType.FINALLY_BODY_START; +import static de.jplag.kotlin.KotlinTokenType.FOR_EXPRESSION_BEGIN; +import static de.jplag.kotlin.KotlinTokenType.FOR_EXPRESSION_END; +import static de.jplag.kotlin.KotlinTokenType.FUNCTION; +import static de.jplag.kotlin.KotlinTokenType.FUNCTION_BODY_BEGIN; +import static de.jplag.kotlin.KotlinTokenType.FUNCTION_BODY_END; +import static de.jplag.kotlin.KotlinTokenType.FUNCTION_INVOCATION; +import static de.jplag.kotlin.KotlinTokenType.FUNCTION_LITERAL_BEGIN; +import static de.jplag.kotlin.KotlinTokenType.FUNCTION_LITERAL_END; +import static de.jplag.kotlin.KotlinTokenType.FUNCTION_PARAMETER; +import static de.jplag.kotlin.KotlinTokenType.GETTER; +import static de.jplag.kotlin.KotlinTokenType.IF_EXPRESSION_BEGIN; +import static de.jplag.kotlin.KotlinTokenType.IF_EXPRESSION_END; +import static de.jplag.kotlin.KotlinTokenType.IMPORT; +import static de.jplag.kotlin.KotlinTokenType.INITIALIZER; +import static de.jplag.kotlin.KotlinTokenType.INITIALIZER_BODY_END; +import static de.jplag.kotlin.KotlinTokenType.INITIALIZER_BODY_START; +import static de.jplag.kotlin.KotlinTokenType.OBJECT_DECLARATION; +import static de.jplag.kotlin.KotlinTokenType.PACKAGE; +import static de.jplag.kotlin.KotlinTokenType.PROPERTY_DECLARATION; +import static de.jplag.kotlin.KotlinTokenType.RETURN; +import static de.jplag.kotlin.KotlinTokenType.SETTER; +import static de.jplag.kotlin.KotlinTokenType.THROW; +import static de.jplag.kotlin.KotlinTokenType.TRY_BODY_END; +import static de.jplag.kotlin.KotlinTokenType.TRY_BODY_START; +import static de.jplag.kotlin.KotlinTokenType.TRY_EXPRESSION; +import static de.jplag.kotlin.KotlinTokenType.TYPE_PARAMETER; +import static de.jplag.kotlin.KotlinTokenType.VARIABLE_DECLARATION; +import static de.jplag.kotlin.KotlinTokenType.WHEN_CONDITION; +import static de.jplag.kotlin.KotlinTokenType.WHEN_EXPRESSION_END; +import static de.jplag.kotlin.KotlinTokenType.WHEN_EXPRESSION_START; +import static de.jplag.kotlin.KotlinTokenType.WHILE_EXPRESSION_END; +import static de.jplag.kotlin.KotlinTokenType.WHILE_EXPRESSION_START; +import static de.jplag.kotlin.grammar.KotlinParser.AnonymousInitializerContext; +import static de.jplag.kotlin.grammar.KotlinParser.AssignmentOperatorContext; +import static de.jplag.kotlin.grammar.KotlinParser.CallSuffixContext; +import static de.jplag.kotlin.grammar.KotlinParser.CatchBodyContext; +import static de.jplag.kotlin.grammar.KotlinParser.CatchStatementContext; +import static de.jplag.kotlin.grammar.KotlinParser.ClassBodyContext; +import static de.jplag.kotlin.grammar.KotlinParser.ClassDeclarationContext; +import static de.jplag.kotlin.grammar.KotlinParser.ClassParameterContext; +import static de.jplag.kotlin.grammar.KotlinParser.CompanionObjectContext; +import static de.jplag.kotlin.grammar.KotlinParser.ConstructorInvocationContext; +import static de.jplag.kotlin.grammar.KotlinParser.ControlStructureBodyContext; +import static de.jplag.kotlin.grammar.KotlinParser.DoWhileExpressionContext; +import static de.jplag.kotlin.grammar.KotlinParser.EnumClassBodyContext; +import static de.jplag.kotlin.grammar.KotlinParser.EnumEntryContext; +import static de.jplag.kotlin.grammar.KotlinParser.FinallyBodyContext; +import static de.jplag.kotlin.grammar.KotlinParser.FinallyStatementContext; +import static de.jplag.kotlin.grammar.KotlinParser.ForExpressionContext; +import static de.jplag.kotlin.grammar.KotlinParser.FunctionBodyContext; +import static de.jplag.kotlin.grammar.KotlinParser.FunctionDeclarationContext; +import static de.jplag.kotlin.grammar.KotlinParser.FunctionLiteralContext; +import static de.jplag.kotlin.grammar.KotlinParser.FunctionValueParameterContext; +import static de.jplag.kotlin.grammar.KotlinParser.GetterContext; +import static de.jplag.kotlin.grammar.KotlinParser.IfExpressionContext; +import static de.jplag.kotlin.grammar.KotlinParser.ImportHeaderContext; +import static de.jplag.kotlin.grammar.KotlinParser.InitBlockContext; +import static de.jplag.kotlin.grammar.KotlinParser.ObjectDeclarationContext; +import static de.jplag.kotlin.grammar.KotlinParser.PackageHeaderContext; +import static de.jplag.kotlin.grammar.KotlinParser.PrimaryConstructorContext; +import static de.jplag.kotlin.grammar.KotlinParser.PropertyDeclarationContext; +import static de.jplag.kotlin.grammar.KotlinParser.SecondaryConstructorContext; +import static de.jplag.kotlin.grammar.KotlinParser.SetterContext; +import static de.jplag.kotlin.grammar.KotlinParser.TryBodyContext; +import static de.jplag.kotlin.grammar.KotlinParser.TryExpressionContext; +import static de.jplag.kotlin.grammar.KotlinParser.TypeParameterContext; +import static de.jplag.kotlin.grammar.KotlinParser.VariableDeclarationContext; +import static de.jplag.kotlin.grammar.KotlinParser.WhenConditionContext; +import static de.jplag.kotlin.grammar.KotlinParser.WhenExpressionContext; +import static de.jplag.kotlin.grammar.KotlinParser.WhileExpressionContext; + +import de.jplag.antlr.AbstractAntlrListener; +import de.jplag.kotlin.grammar.KotlinParser; + +class KotlinListener extends AbstractAntlrListener { + + KotlinListener() { + visit(PackageHeaderContext.class).map(PACKAGE); + visit(ImportHeaderContext.class).map(IMPORT); + visit(ClassDeclarationContext.class).map(CLASS_DECLARATION); + visit(ObjectDeclarationContext.class).map(OBJECT_DECLARATION); + visit(CompanionObjectContext.class).map(COMPANION_DECLARATION); + visit(TypeParameterContext.class).map(TYPE_PARAMETER); + visit(PrimaryConstructorContext.class).map(CONSTRUCTOR); + visit(ClassParameterContext.class).map(PROPERTY_DECLARATION); + visit(ClassBodyContext.class).map(CLASS_BODY_BEGIN, CLASS_BODY_END); + visit(EnumClassBodyContext.class).map(ENUM_CLASS_BODY_BEGIN, ENUM_CLASS_BODY_END); + visit(EnumEntryContext.class).map(ENUM_ENTRY); + visit(SecondaryConstructorContext.class).map(CONSTRUCTOR); + visit(PropertyDeclarationContext.class).map(PROPERTY_DECLARATION); + visit(AnonymousInitializerContext.class).map(INITIALIZER); + visit(InitBlockContext.class).map(INITIALIZER_BODY_START, INITIALIZER_BODY_END); + visit(FunctionDeclarationContext.class).map(FUNCTION); + visit(GetterContext.class).map(GETTER); + visit(SetterContext.class).map(SETTER); + visit(FunctionValueParameterContext.class).map(FUNCTION_PARAMETER); + visit(FunctionBodyContext.class).map(FUNCTION_BODY_BEGIN, FUNCTION_BODY_END); + visit(FunctionLiteralContext.class).map(FUNCTION_LITERAL_BEGIN, FUNCTION_LITERAL_END); + visit(ForExpressionContext.class).map(FOR_EXPRESSION_BEGIN, FOR_EXPRESSION_END); + visit(IfExpressionContext.class).map(IF_EXPRESSION_BEGIN, IF_EXPRESSION_END); + visit(WhileExpressionContext.class).map(WHILE_EXPRESSION_START, WHILE_EXPRESSION_END); + visit(DoWhileExpressionContext.class).map(DO_WHILE_EXPRESSION_START, DO_WHILE_EXPRESSION_END); + visit(TryExpressionContext.class).map(TRY_EXPRESSION); + visit(TryBodyContext.class).map(TRY_BODY_START, TRY_BODY_END); + visit(CatchStatementContext.class).map(CATCH); + visit(CatchBodyContext.class).map(CATCH_BODY_START, CATCH_BODY_END); + visit(FinallyStatementContext.class).map(FINALLY); + visit(FinallyBodyContext.class).map(FINALLY_BODY_START, FINALLY_BODY_END); + visit(WhenExpressionContext.class).map(WHEN_EXPRESSION_START, WHEN_EXPRESSION_END); + visit(WhenConditionContext.class).map(WHEN_CONDITION); + visit(ControlStructureBodyContext.class).map(CONTROL_STRUCTURE_BODY_START, CONTROL_STRUCTURE_BODY_END); + visit(VariableDeclarationContext.class).map(VARIABLE_DECLARATION); + visit(ConstructorInvocationContext.class).map(CREATE_OBJECT); + visit(CallSuffixContext.class).map(FUNCTION_INVOCATION); + visit(AssignmentOperatorContext.class).map(ASSIGNMENT); + + visit(KotlinParser.THROW).map(THROW); + visit(KotlinParser.RETURN).map(RETURN); + visit(KotlinParser.CONTINUE).map(CONTINUE); + visit(KotlinParser.BREAK).map(BREAK); + visit(KotlinParser.BREAK_AT).map(BREAK); + } +} diff --git a/languages/kotlin/src/main/java/de/jplag/kotlin/KotlinParserAdapter.java b/languages/kotlin/src/main/java/de/jplag/kotlin/KotlinParserAdapter.java index fdf9c9b92..0fed85032 100644 --- a/languages/kotlin/src/main/java/de/jplag/kotlin/KotlinParserAdapter.java +++ b/languages/kotlin/src/main/java/de/jplag/kotlin/KotlinParserAdapter.java @@ -1,78 +1,32 @@ package de.jplag.kotlin; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; +import org.antlr.v4.runtime.*; -import org.antlr.v4.runtime.CharStreams; -import org.antlr.v4.runtime.CommonTokenStream; -import org.antlr.v4.runtime.ParserRuleContext; -import org.antlr.v4.runtime.tree.ParseTree; -import org.antlr.v4.runtime.tree.ParseTreeWalker; - -import de.jplag.AbstractParser; -import de.jplag.ParsingException; -import de.jplag.Token; +import de.jplag.antlr.AbstractAntlrListener; +import de.jplag.antlr.AbstractAntlrParserAdapter; import de.jplag.kotlin.grammar.KotlinLexer; import de.jplag.kotlin.grammar.KotlinParser; -public class KotlinParserAdapter extends AbstractParser { - private File currentFile; - private List tokens; +public class KotlinParserAdapter extends AbstractAntlrParserAdapter { + private static final KotlinListener listener = new KotlinListener(); - /** - * Creates the KotlinParserAdapter - */ - public KotlinParserAdapter() { - super(); + @Override + protected Lexer createLexer(CharStream input) { + return new KotlinLexer(input); } - /** - * Parsers a set of files into a single list of {@link Token}s. - * @param files the set of files. - * @return a list containing all tokens of all files. - */ - public List parse(Set files) throws ParsingException { - tokens = new ArrayList<>(); - for (File file : files) { - parseFile(file); - tokens.add(Token.fileEnd(file)); - } - return tokens; + @Override + protected KotlinParser createParser(CommonTokenStream tokenStream) { + return new KotlinParser(tokenStream); } - private void parseFile(File file) throws ParsingException { - try (FileInputStream inputStream = new FileInputStream(file)) { - currentFile = file; - - KotlinLexer lexer = new KotlinLexer(CharStreams.fromStream(inputStream)); - CommonTokenStream tokenStream = new CommonTokenStream(lexer); - KotlinParser parser = new KotlinParser(tokenStream); - - ParserRuleContext entryContext = parser.kotlinFile(); - ParseTreeWalker treeWalker = new ParseTreeWalker(); - - JPlagKotlinListener listener = new JPlagKotlinListener(this); - for (int i = 0; i < entryContext.getChildCount(); i++) { - ParseTree parseTree = entryContext.getChild(i); - treeWalker.walk(listener, parseTree); - } - } catch (IOException exception) { - throw new ParsingException(file, exception.getMessage(), exception); - } + @Override + protected ParserRuleContext getEntryContext(KotlinParser parser) { + return parser.kotlinFile(); } - /** - * Adds a new {@link Token} to the current token list. - * @param tokenType the type of the new {@link Token} - * @param line the line of the Token in the current file - * @param column the start column of the Token in the line - * @param length the length of the Token - */ - /* package-private */ void addToken(KotlinTokenType tokenType, int line, int column, int length) { - tokens.add(new Token(tokenType, currentFile, line, column, length)); + @Override + protected AbstractAntlrListener getListener() { + return listener; } } diff --git a/languages/kotlin/src/main/java/de/jplag/kotlin/KotlinTokenType.java b/languages/kotlin/src/main/java/de/jplag/kotlin/KotlinTokenType.java index 758ee0264..318b2b17a 100644 --- a/languages/kotlin/src/main/java/de/jplag/kotlin/KotlinTokenType.java +++ b/languages/kotlin/src/main/java/de/jplag/kotlin/KotlinTokenType.java @@ -38,7 +38,7 @@ public enum KotlinTokenType implements TokenType { FOR_EXPRESSION_BEGIN("FOR"), FOR_EXPRESSION_END("}FOR"), - IF_EXPRESSION_START("IF"), + IF_EXPRESSION_BEGIN("IF"), IF_EXPRESSION_END("}IF(-ELSE)"), WHILE_EXPRESSION_START("WHILE"), @@ -76,6 +76,7 @@ public enum KotlinTokenType implements TokenType { private final String description; + @Override public String getDescription() { return description; } diff --git a/languages/kotlin/src/test/java/de/jplag/kotlin/KotlinLanguageTest.java b/languages/kotlin/src/test/java/de/jplag/kotlin/KotlinLanguageTest.java index 1d0ec1034..335558d91 100644 --- a/languages/kotlin/src/test/java/de/jplag/kotlin/KotlinLanguageTest.java +++ b/languages/kotlin/src/test/java/de/jplag/kotlin/KotlinLanguageTest.java @@ -1,150 +1,30 @@ package de.jplag.kotlin; -import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Arrays; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import de.jplag.ParsingException; -import de.jplag.SharedTokenType; -import de.jplag.Token; -import de.jplag.TokenPrinter; - -class KotlinLanguageTest { - - /** - * Test source file that is supposed to produce a complete set of tokens, i.e. all types of tokens. - */ - private static final String COMPLETE_TEST_FILE = "Complete.kt"; - - /** - * Regular expression that describes lines consisting only of whitespace and optionally a line comment. - */ - private static final String EMPTY_OR_SINGLE_LINE_COMMENT = "\\s*(//.*|/\\*.*\\*/)?"; - - /** - * Regular expression that describes lines containing the start of a multiline comment and no code before it. - */ - private static final String DELIMITED_COMMENT_START = "\\s*/\\*(?:(?!\\*/).)*$"; - - /** - * Regular expression that describes lines containing the end of a multiline comment and no more code after that. - */ - private static final String DELIMITED_COMMENT_END = ".*\\*/\\s*$"; - - private final Logger logger = LoggerFactory.getLogger(KotlinLanguageTest.class); - private final String[] testFiles = new String[] {COMPLETE_TEST_FILE, "Game.kt"}; - private final File testFileLocation = Path.of("src", "test", "resources", "de", "jplag", "kotlin").toFile(); - private Language language; - - @BeforeEach - void setup() { - language = new Language(); +import de.jplag.testutils.LanguageModuleTest; +import de.jplag.testutils.datacollector.TestDataCollector; +import de.jplag.testutils.datacollector.TestSourceIgnoredLinesCollector; + +/** + * Provides tests for the kotlin language module + */ +public class KotlinLanguageTest extends LanguageModuleTest { + public KotlinLanguageTest() { + super(new KotlinLanguage(), KotlinTokenType.class); } - @Test - void parseTestFiles() throws ParsingException { - for (String fileName : testFiles) { - List tokens = language.parse(Set.of(new File(testFileLocation, fileName))); - String output = TokenPrinter.printTokens(tokens, testFileLocation); - logger.info(output); + @Override + protected void collectTestData(TestDataCollector collector) { + collector.testFile("Complete.kt").testCoverages(); + collector.testFile("Game.kt").testSourceCoverage(); - testSourceCoverage(fileName, tokens); - if (fileName.equals(COMPLETE_TEST_FILE)) { - testTokenCoverage(tokens, fileName); - } + collector.testFile("HelloWorld.kt").testSourceCoverage().testTokenSequence(KotlinTokenType.PACKAGE, KotlinTokenType.FUNCTION, + KotlinTokenType.FUNCTION_BODY_BEGIN, KotlinTokenType.FUNCTION_INVOCATION, KotlinTokenType.FUNCTION_BODY_END); - } + collector.inlineSource("package de.jplag.kotlin\n").testSourceCoverage().testContainedTokens(KotlinTokenType.PACKAGE); } - /** - * Confirms that the code is covered to a basic extent, i.e. each line of code contains at least one token. - * @param fileName a code sample file name - * @param tokens the list of tokens generated from the sample - */ - private void testSourceCoverage(String fileName, List tokens) { - File testFile = new File(testFileLocation, fileName); - - try { - List lines = Files.readAllLines(testFile.toPath()); - - // All lines that contain code - var codeLines = getCodeLines(lines); - // All lines that contain token - var tokenLines = tokens.stream().mapToInt(Token::getLine).filter(line -> line != Token.NO_VALUE).distinct().toArray(); - - if (codeLines.length > tokenLines.length) { - var diffLine = IntStream.range(0, codeLines.length) - .dropWhile(lineIdx -> lineIdx < tokenLines.length && codeLines[lineIdx] == tokenLines[lineIdx]).findFirst(); - diffLine.ifPresent( - lineIdx -> fail("Line %d of file '%s' is not represented in the token list.".formatted(codeLines[lineIdx], fileName))); - } - assertArrayEquals(codeLines, tokenLines); - } catch (IOException exception) { - logger.info("Error while reading test file %s".formatted(fileName), exception); - fail(); - } - } - - /** - * Gets the line numbers of lines containing actual code, omitting empty lines and comment lines. - * @param lines lines of a code file - * @return an array of the line numbers of code lines - */ - private int[] getCodeLines(List lines) { - // This boxed boolean can be accessed from within the lambda method below - var state = new Object() { - boolean insideComment = false; - }; - - var codeLines = IntStream.rangeClosed(1, lines.size()).sequential().filter(idx -> { - String line = lines.get(idx - 1); - if (line.matches(EMPTY_OR_SINGLE_LINE_COMMENT)) { - return false; - } else if (line.matches(DELIMITED_COMMENT_START)) { - state.insideComment = true; - return false; - } else if (state.insideComment) { - // This fails if code follows after '*/'. If the code is formatted well, this should not happen. - if (line.matches(DELIMITED_COMMENT_END)) { - state.insideComment = false; - } - return false; - } - return true; - }); - - return codeLines.toArray(); - + @Override + protected void configureIgnoredLines(TestSourceIgnoredLinesCollector collector) { + collector.ignoreMultipleLines("/*", "*/"); } - - /** - * Confirms that all Token types are 'reachable' with a complete code example. - * @param tokens list of tokens which is supposed to contain all types of tokens - * @param fileName The file name of the complete code example - */ - private void testTokenCoverage(List tokens, String fileName) { - var annotatedTokens = tokens.stream().map(Token::getType).collect(Collectors.toSet()); - assertTrue(annotatedTokens.contains(SharedTokenType.FILE_END)); - var annotatedKotlinTokens = annotatedTokens.stream().filter(KotlinTokenType.class::isInstance).collect(Collectors.toSet()); - var allKotlinTokens = KotlinTokenType.values(); - var missingKotlinTokens = Arrays.stream(allKotlinTokens).filter(token -> !annotatedKotlinTokens.contains(token)).toList(); - assertTrue(missingKotlinTokens.isEmpty(), "The following kotlin tokens are missing in the code example '%s':\n".formatted(fileName) - + String.join("\n", missingKotlinTokens.stream().map(KotlinTokenType::getDescription).toList())); - } - -} \ No newline at end of file +} diff --git a/languages/kotlin/src/test/resources/de/jplag/kotlin/HelloWorld.kt b/languages/kotlin/src/test/resources/de/jplag/kotlin/HelloWorld.kt new file mode 100644 index 000000000..fe9cefde8 --- /dev/null +++ b/languages/kotlin/src/test/resources/de/jplag/kotlin/HelloWorld.kt @@ -0,0 +1,5 @@ +package de.jplag.kotlin + +fun main() { + println("Hello World") +} diff --git a/languages/llvmir/README.md b/languages/llvmir/README.md new file mode 100644 index 000000000..a006a51d2 --- /dev/null +++ b/languages/llvmir/README.md @@ -0,0 +1,42 @@ +# JPlag LLVM IR language module + +The JPlag LLVM IR module allows the use of JPlag with submissions in the LLVM IR.
+It is based on the [LLVMIR ANTLR4 grammar](https://github.com/antlr/grammars-v4/tree/master/llvm-ir), licensed under MIT. + +### LLVM IR specification compatibility + +The grammar definition targets LLVM 15, released in September 2022. + +The grammar in this repo contains a fix, see the comment in the [LLVM IR grammar](src/main/antlr4/de/jplag/llvmir/grammar/LLVMIR.g4). + +If the grammar is updated to a more recent1 syntax definition, this module should surely be updated as well. + + +### Token Extraction + +The choice of tokens includes nesting tokens for functions and basic blocks and separate tokens for various elements. +These include binary and bitwise instructions (like addition and or), memory operations (like load and store), terminator instructions (like branches), conversions, global variables, type definitions, constants and others. + + +### Usage + +To use the LLVM IR module, add the `-l llvmir` flag in the CLI, or use a `JPlagOption` object with `new de.jplag.llvmir.LLVMIRLanguage()` as `language` in the Java API as described in the usage information in the [readme of the main project](https://github.com/jplag/JPlag#usage) and [in the wiki](https://github.com/jplag/JPlag/wiki/1.-How-to-Use-JPlag). + +We recommend using the [LLVM optimizer](https://llvm.org/docs/CommandGuide/opt.html) to optimize the LLVM IR code before using JPlag. +In our tests, optimization level 1 showed the best results in plagiarism detection quality and should therefore, be used. + +### Minimum Token Match + +It can be difficult to find a good value for the minimum token match because the range of possible candidates for low-level languages like the LLVM IR is much larger. +Values can range between 60 and 70 for code compiled from C to more than 1000 for code compiled from C++. +From our tests, we calculated a formula that depends on the average lines of code (avg. loc) to determine a value that should provide good results: + +min_token_match(x) = 48.2055162 * e^(0.000333593799 * x) + +with x = (avg. loc of the LLVM IR code) - (avg. loc of the source code),
+where the source code is the code from which the IR code was generated, for example, the C or C++ code. + +
+ +#### Footnotes +
1 The grammar files are taken from grammar-v4, with the most recent modification in commit 768b12e from August 2023.
\ No newline at end of file diff --git a/languages/llvmir/pom.xml b/languages/llvmir/pom.xml new file mode 100644 index 000000000..c5306fb4c --- /dev/null +++ b/languages/llvmir/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + + + de.jplag + languages + ${revision} + + llvmir + + + + org.antlr + antlr4-runtime + + + de.jplag + language-antlr-utils + ${revision} + + + + + + + org.antlr + antlr4-maven-plugin + + + + antlr4 + + + + + + + diff --git a/languages/llvmir/src/main/antlr4/de/jplag/llvmir/grammar/LLVMIR.g4 b/languages/llvmir/src/main/antlr4/de/jplag/llvmir/grammar/LLVMIR.g4 new file mode 100644 index 000000000..ffb1eab85 --- /dev/null +++ b/languages/llvmir/src/main/antlr4/de/jplag/llvmir/grammar/LLVMIR.g4 @@ -0,0 +1,1445 @@ +/* + MIT License + + Copyright (c) 2023 ้‚ฑ็ปดไธœ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + Modifications: + Rename 'case' rule to 'case_' to match the generated case_() method in the LLVMIRParser + with the JavaDoc of the enterCase() and exitCase() methods of the LLVMIRListener + to fix a JavaDoc issue. + - Niklas Heneka + */ + +grammar LLVMIR; + +compilationUnit: topLevelEntity* EOF; + +targetDef: targetDataLayout | targetTriple; +sourceFilename: 'source_filename' '=' StringLit; +targetDataLayout: 'target' 'datalayout' '=' StringLit; +targetTriple: 'target' 'triple' '=' StringLit; + +topLevelEntity: + sourceFilename + | targetDef + | moduleAsm + | typeDef + | comdatDef + | globalDecl + | globalDef + | indirectSymbolDef + | funcDecl + | funcDef + | attrGroupDef + | namedMetadataDef + | metadataDef + | useListOrder + | useListOrderBB; +moduleAsm: 'module' 'asm' StringLit; +typeDef: LocalIdent '=' 'type' type; +comdatDef: + ComdatName '=' 'comdat' selectionKind = ( + 'any' + | 'exactmatch' + | 'largest' + | 'nodeduplicate' + | 'samesize' + ); +globalDecl: + GlobalIdent '=' externalLinkage preemption? visibility? dllStorageClass? threadLocal? + unnamedAddr? addrSpace? externallyInitialized? immutable type ( + ',' globalField + )* (',' metadataAttachment)* funcAttribute*; +globalDef: + GlobalIdent '=' internalLinkage? preemption? visibility? dllStorageClass? threadLocal? + unnamedAddr? addrSpace? externallyInitialized? immutable type constant ( + ',' globalField + )* (',' metadataAttachment)* funcAttribute*; + +indirectSymbolDef: + GlobalIdent '=' linkage? preemption? visibility? dllStorageClass? threadLocal? unnamedAddr? + indirectSymbolKind = ('alias' | 'ifunc') type ',' indirectSymbol ( + ',' partition + )*; + +funcDecl: 'declare' metadataAttachment* funcHeader; +funcDef: 'define' funcHeader metadataAttachment* funcBody; +attrGroupDef: + 'attributes' AttrGroupId '=' '{' funcAttribute* '}'; +namedMetadataDef: + MetadataName '=' '!' '{' (metadataNode (',' metadataNode)*)? '}'; +metadataDef: + MetadataId '=' distinct? (mdTuple | specializedMDNode); +useListOrder: + 'uselistorder' typeValue ',' '{' IntLit (',' IntLit)* '}'; +useListOrderBB: + 'uselistorder_bb' GlobalIdent ',' LocalIdent ',' '{' IntLit ( + ',' IntLit + )* '}'; + +funcHeader: + linkage? preemption? visibility? dllStorageClass? callingConv? returnAttribute* type GlobalIdent + '(' params ')' unnamedAddr? addrSpace? funcHdrField*; +indirectSymbol: + typeConst + | bitCastExpr + | getElementPtrExpr + | addrSpaceCastExpr + | intToPtrExpr; +callingConv: callingConvEnum | callingConvInt; +callingConvInt: 'cc' IntLit; +funcHdrField: + funcAttribute + | section + | partition + | comdat + | align + | gc + | prefix + | prologue + | personality; +gc: 'gc' StringLit; +prefix: 'prefix' typeConst; +prologue: 'prologue' typeConst; +personality: 'personality' typeConst; +returnAttribute: + returnAttr + | dereferenceable + | align; +funcBody: '{' basicBlock+ useListOrder* '}'; +basicBlock: LabelIdent? instruction* terminator; +instruction: // Instructions producing values. + localDefInst + | valueInstruction + // Instructions not producing values. + | storeInst + | fenceInst; +terminator: + // Terminators producing values. + localDefTerm + | valueTerminator + // Terminators not producing values. + | retTerm + | brTerm + | condBrTerm + | switchTerm + | indirectBrTerm + | resumeTerm + | catchRetTerm + | cleanupRetTerm + | unreachableTerm; +localDefTerm: LocalIdent '=' valueTerminator; +valueTerminator: invokeTerm | callBrTerm | catchSwitchTerm; +retTerm: + 'ret' 'void' (',' metadataAttachment)* + // Value return. + | 'ret' concreteType value (',' metadataAttachment)*; +brTerm: 'br' label (',' metadataAttachment)*; +condBrTerm: + 'br' IntType value ',' label ',' label ( + ',' metadataAttachment + )*; +switchTerm: + 'switch' typeValue ',' label '[' case_* ']' ( + ',' metadataAttachment + )*; +indirectBrTerm: + 'indirectbr' typeValue ',' '[' (label (',' label)?)? ']' ( + ',' metadataAttachment + )*; +resumeTerm: 'resume' typeValue (',' metadataAttachment)*; +catchRetTerm: + 'catchret' 'from' value 'to' label (',' metadataAttachment)*; +cleanupRetTerm: + 'cleanupret' 'from' value 'unwind' unwindTarget ( + ',' metadataAttachment + )*; +unreachableTerm: 'unreachable' (',' metadataAttachment)*; +invokeTerm: + 'invoke' callingConv? returnAttribute* addrSpace? type value '(' args ')' funcAttribute* ( + '[' (operandBundle ',')+ ']' + )? 'to' label 'unwind' label (',' metadataAttachment)*; +callBrTerm: + 'callbr' callingConv? returnAttribute* addrSpace? type value '(' args ')' funcAttribute* ( + '[' (operandBundle ',')+ ']' + )? 'to' label '[' (label (',' label)*)? ']' ( + ',' metadataAttachment + )*; +catchSwitchTerm: + 'catchswitch' 'within' exceptionPad '[' handlers ']' 'unwind' unwindTarget ( + ',' metadataAttachment + )*; +label: 'label' LocalIdent; +case_: typeConst ',' label; +unwindTarget: 'to' 'caller' | label; +handlers: label (',' label)*; +metadataNode: + MetadataId + // Parse DIExpressions inline as a special case. They are still MDNodes, so they can still + // appear in named metadata. Remove this logic if they become plain Metadata. + | diExpression; +diExpression: + '!DIExpression' '(' ( + diExpressionField (',' diExpressionField)* + )? ')'; +diExpressionField: IntLit | DwarfAttEncoding | DwarfOp; + +globalField: + section + | partition + | comdat + | align + | sanitizerKind = ( + 'no_sanitize_address' + | 'no_sanitize_hwaddress' + | 'sanitize_address_dyninit' + | 'sanitize_memtag' + ); +section: 'section' StringLit; +comdat: 'comdat' ('(' ComdatName ')')?; +partition: 'partition' StringLit; + +constant: + boolConst + | intConst + | floatConst + | nullConst + | noneConst + | structConst + | arrayConst + | vectorConst + | zeroInitializerConst + // @42 @foo + | GlobalIdent + | undefConst + | poisonConst + | blockAddressConst + | dsoLocalEquivalentConst + | noCFIConst + | constantExpr; +boolConst: 'true' | 'false'; +intConst: IntLit; +floatConst: FloatLit; +nullConst: 'null'; +noneConst: 'none'; +structConst: + '{' (typeConst (',' typeConst)*)? '}' + | '<' '{' ( typeConst (',' typeConst)*)? '}' '>'; +arrayConst: + 'c' StringLit + | '[' (typeConst (',' typeConst)*)? ']'; +vectorConst: '<' (typeConst (',' typeConst)*)? '>'; +zeroInitializerConst: 'zeroinitializer'; +undefConst: 'undef'; +poisonConst: 'poison'; +blockAddressConst: + 'blockaddress' '(' GlobalIdent ',' LocalIdent ')'; +dsoLocalEquivalentConst: 'dso_local_equivalent' GlobalIdent; +noCFIConst: 'no_cfi' GlobalIdent; +constantExpr: + // Unary expressions + fNegExpr + // Binary expressions + | addExpr + | subExpr + | mulExpr + // Bitwise expressions + | shlExpr + | lShrExpr + | aShrExpr + | andExpr + | orExpr + | xorExpr + // Vector expressions + | extractElementExpr + | insertElementExpr + | shuffleVectorExpr + // Memory expressions + | getElementPtrExpr + // Conversion expressions + | truncExpr + | zExtExpr + | sExtExpr + | fpTruncExpr + | fpExtExpr + | fpToUiExpr + | fpToSiExpr + | uiToFpExpr + | siToFpExpr + | ptrToIntExpr + | intToPtrExpr + | bitCastExpr + | addrSpaceCastExpr + // Other expressions + | iCmpExpr + | fCmpExpr + | selectExpr; +typeConst: firstClassType constant; + +metadataAttachment: MetadataName mdNode; +mdNode: + mdTuple + // !42 + | MetadataId + //!{ ... } + | specializedMDNode; +mdTuple: '!' '{' (mdField (',' mdField)*)? '}'; +// metadataID: MetadataId; +metadata: + typeValue + | mdString + // !{ ... } + | mdTuple + // !7 + | MetadataId + | diArgList + | specializedMDNode; +diArgList: '!DIArgList' '(' (typeValue (',' typeValue)*)? ')'; +typeValue: firstClassType value; +value: + constant + // %42 %foo + | LocalIdent + // TODO: Move InlineAsm from Value to Callee and Invokee? Inline assembler expressions may only + // be used as the callee operand of a call or an invoke instruction. + | inlineAsm; +inlineAsm: + 'asm' sideEffect = 'sideeffect'? alignStackTok = 'alignstack'? intelDialect = 'inteldialect'? + unwind = 'unwind'? StringLit ',' StringLit; +mdString: '!' StringLit; +mdFieldOrInt: IntLit | mdField; +diSPFlag: IntLit | DispFlag; +funcAttribute: + attrString + | attrPair + // not used in attribute groups. + | AttrGroupId + // used in functions. | align # NOTE: removed to resolve reduce/reduce conflict, see above. used + // in attribute groups. + | alignPair + | alignStack + | alignStackPair + | allocKind + | allocSize + | funcAttr + | preallocated + | unwindTable + | vectorScaleRange; +type: + 'void' + | 'opaque' + | type '(' params ')' + | intType + | floatType + | type addrSpace? '*' + | opaquePointerType + | vectorType + | labelType + | arrayType + | structType + | namedType + | mmxType + | tokenType + | metadataType; +params: + ellipsis = '...'? + | param (',' param)* (',' ellipsis = '...')?; +param: type paramAttribute* LocalIdent?; +paramAttribute: + attrString + | attrPair + | align + | alignStack + | byRefAttr + | byval + | dereferenceable + | elementType + | inAlloca + | paramAttr + | preallocated + | structRetAttr; +attrString: StringLit; +attrPair: StringLit '=' StringLit; +align: 'align' IntLit | 'align' '(' IntLit ')'; +alignPair: 'align' '=' IntLit; +alignStack: 'alignstack' '(' IntLit ')'; +alignStackPair: 'alignstack' '=' IntLit; +allocKind: 'allockind' '(' StringLit ')'; +allocSize: 'allocsize' '(' IntLit (',' IntLit)? ')'; +unwindTable: + 'uwtable' + | 'uwtable' '(' unwindTableKind = ('async' | 'sync') ')'; +vectorScaleRange: + 'vscale_range' ('(' (IntLit | IntLit ',' IntLit) ')')?; +byRefAttr: 'byref' '(' type ')'; +byval: 'byval' ( '(' type ')')?; +dereferenceable: + 'dereferenceable' '(' IntLit ')' + | 'dereferenceable_or_null' '(' IntLit ')'; +elementType: 'elementtype' '(' type ')'; +inAlloca: 'inalloca' '(' type ')'; +paramAttr: + 'allocalign' + | 'allocptr' + | 'immarg' + | 'inreg' + | 'nest' + | 'noalias' + | 'nocapture' + | 'nofree' + | 'nonnull' + | 'noundef' + | 'readnone' + | 'readonly' + | 'returned' + | 'signext' + | 'swiftasync' + | 'swifterror' + | 'swiftself' + | 'writeonly' + | 'zeroext'; +preallocated: 'preallocated' '(' type ')'; +structRetAttr: 'sret' '(' type ')'; + +// funcType: type '(' params ')'; +firstClassType: concreteType | metadataType; +concreteType: + intType + | floatType + | pointerType + | vectorType + | labelType + | arrayType + | structType + | namedType + | mmxType + | tokenType; + +intType: IntType; +floatType: floatKind; +pointerType: type addrSpace? '*' | opaquePointerType; +vectorType: + '<' IntLit 'x' type '>' + | '<' 'vscale' 'x' IntLit 'x' type '>'; +labelType: 'label'; +arrayType: '[' IntLit 'x' type ']'; +structType: + '{' (type (',' type)*)? '}' + | '<' '{' (type (',' type)*)? '}' '>'; +namedType: LocalIdent; +mmxType: 'x86_mmx'; +tokenType: 'token'; + +opaquePointerType: 'ptr' addrSpace?; +addrSpace: 'addrspace' '(' IntLit ')'; +threadLocal: 'thread_local' ('(' tlsModel ')')?; +metadataType: 'metadata'; + +// expr +bitCastExpr: 'bitcast' '(' typeConst 'to' type ')'; +getElementPtrExpr: + 'getelementptr' inBounds? '(' type ',' typeConst ( + ',' gepIndex + )* ')'; +gepIndex: inRange = 'inrange'? typeConst; +addrSpaceCastExpr: 'addrspacecast' '(' typeConst 'to' type ')'; +intToPtrExpr: 'inttoptr' '(' typeConst 'to' type ')'; +iCmpExpr: 'icmp' iPred '(' typeConst ',' typeConst ')'; +fCmpExpr: 'fcmp' fPred '(' typeConst ',' typeConst ')'; +selectExpr: + 'select' '(' typeConst ',' typeConst ',' typeConst ')'; + +truncExpr: 'trunc' '(' typeConst 'to' type ')'; +zExtExpr: 'zext' '(' typeConst 'to' type ')'; +sExtExpr: 'sext' '(' typeConst 'to' type ')'; +fpTruncExpr: 'fptrunc' '(' typeConst 'to' type ')'; +fpExtExpr: 'fpext' '(' typeConst 'to' type ')'; +fpToUiExpr: 'fptoui' '(' typeConst 'to' type ')'; +fpToSiExpr: 'fptosi' '(' typeConst 'to' type ')'; +uiToFpExpr: 'uitofp' '(' typeConst 'to' type ')'; +siToFpExpr: 'sitofp' '(' typeConst 'to' type ')'; +ptrToIntExpr: 'ptrtoint' '(' typeConst 'to' type ')'; +extractElementExpr: + 'extractelement' '(' typeConst ',' typeConst ')'; +insertElementExpr: + 'insertelement' '(' typeConst ',' typeConst ',' typeConst ')'; +shuffleVectorExpr: + 'shufflevector' '(' typeConst ',' typeConst ',' typeConst ')'; +shlExpr: 'shl' overflowFlag* '(' typeConst ',' typeConst ')'; +lShrExpr: + 'lshr' exact = 'exact'? '(' typeConst ',' typeConst ')'; +aShrExpr: + 'ashr' exact = 'exact'? '(' typeConst ',' typeConst ')'; +andExpr: 'and' '(' typeConst ',' typeConst ')'; +orExpr: 'or' '(' typeConst ',' typeConst ')'; +xorExpr: 'xor' '(' typeConst ',' typeConst ')'; +addExpr: 'add' overflowFlag* '(' typeConst ',' typeConst ')'; +subExpr: 'sub' overflowFlag* '(' typeConst ',' typeConst ')'; +mulExpr: 'mul' overflowFlag* '(' typeConst ',' typeConst ')'; +fNegExpr: 'fneg' '(' typeConst ')'; + +// instructions +localDefInst: LocalIdent '=' valueInstruction; +valueInstruction: + // Unary instructions + fNegInst + // Binary instructions + | addInst + | fAddInst + | subInst + | fSubInst + | mulInst + | fMulInst + | uDivInst + | sDivInst + | fDivInst + | uRemInst + | sRemInst + | fRemInst + // Bitwise instructions + | shlInst + | lShrInst + | aShrInst + | andInst + | orInst + | xorInst + // Vector instructions + | extractElementInst + | insertElementInst + | shuffleVectorInst + // Aggregate instructions + | extractValueInst + | insertValueInst + // Memory instructions + | allocaInst + | loadInst + | cmpXchgInst + | atomicRMWInst + | getElementPtrInst + // Conversion instructions + | truncInst + | zExtInst + | sExtInst + | fpTruncInst + | fpExtInst + | fpToUiInst + | fpToSiInst + | uiToFpInst + | siToFpInst + | ptrToIntInst + | intToPtrInst + | bitCastInst + | addrSpaceCastInst + // Other instructions + | iCmpInst + | fCmpInst + | phiInst + | selectInst + | freezeInst + | callInst + | vaargInst + | landingPadInst + | catchPadInst + | cleanupPadInst; +storeInst: + // Store. + 'store' volatile = 'volatile'? typeValue ',' typeValue ( + ',' align + )? (',' metadataAttachment)* + // atomic='atomic' store. + | 'store' atomic = 'atomic' volatile = 'volatile'? typeValue ',' typeValue syncScope? + atomicOrdering (',' align)? (',' metadataAttachment)*; + +syncScope: 'syncscope' '(' StringLit ')'; + +fenceInst: + 'fence' syncScope? atomicOrdering (',' metadataAttachment)*; +fNegInst: + 'fneg' fastMathFlag* typeValue (',' metadataAttachment)*; +addInst: + 'add' overflowFlag* typeValue ',' value ( + ',' metadataAttachment + )*; +fAddInst: + 'fadd' fastMathFlag* typeValue ',' value ( + ',' metadataAttachment + )*; +subInst: + 'sub' overflowFlag* typeValue ',' value ( + ',' metadataAttachment + )*; +fSubInst: + 'fsub' fastMathFlag* typeValue ',' value ( + ',' metadataAttachment + )*; +mulInst: + 'mul' overflowFlag* typeValue ',' value ( + ',' metadataAttachment + )*; +fMulInst: + 'fmul' fastMathFlag* typeValue ',' value ( + ',' metadataAttachment + )*; +uDivInst: + 'udiv' exact = 'exact'? typeValue ',' value ( + ',' metadataAttachment + )*; +sDivInst: + 'sdiv' exact = 'exact'? typeValue ',' value ( + ',' metadataAttachment + )*; +fDivInst: + 'fdiv' fastMathFlag* typeValue ',' value ( + ',' metadataAttachment + )*; +uRemInst: 'urem' typeValue ',' value ( ',' metadataAttachment)*; +sRemInst: 'srem' typeValue ',' value ( ',' metadataAttachment)*; +fRemInst: + 'frem' fastMathFlag* typeValue ',' value ( + ',' metadataAttachment + )*; +shlInst: + 'shl' overflowFlag* typeValue ',' value ( + ',' metadataAttachment + )*; +lShrInst: + 'lshr' exact = 'exact'? typeValue ',' value ( + ',' metadataAttachment + )*; +aShrInst: + 'ashr' exact = 'exact'? typeValue ',' value ( + ',' metadataAttachment + )*; +andInst: 'and' typeValue ',' value ( ',' metadataAttachment)*; +orInst: 'or' typeValue ',' value ( ',' metadataAttachment)*; +xorInst: 'xor' typeValue ',' value ( ',' metadataAttachment)*; +extractElementInst: + 'extractelement' typeValue ',' typeValue ( + ',' metadataAttachment + )*; +insertElementInst: + 'insertelement' typeValue ',' typeValue ',' typeValue ( + ',' metadataAttachment + )*; +shuffleVectorInst: + 'shufflevector' typeValue ',' typeValue ',' typeValue ( + ',' metadataAttachment + )*; +extractValueInst: + 'extractvalue' typeValue (',' IntLit)+ ( + ',' metadataAttachment + )*; +insertValueInst: + 'insertvalue' typeValue ',' typeValue (',' IntLit)+ ( + ',' metadataAttachment + )*; +allocaInst: + 'alloca' inAllocaTok = 'inalloca'? swiftError = 'swifterror'? type ( + ',' typeValue + )? (',' align)? (',' addrSpace)? (',' metadataAttachment)*; +loadInst: + // Load. + 'load' volatile = 'volatile'? type ',' typeValue (',' align)? ( + ',' metadataAttachment + )* + // atomic='atomic' load. + | 'load' atomic = 'atomic' volatile = 'volatile'? type ',' typeValue syncScope? atomicOrdering ( + ',' align + )? (',' metadataAttachment)*; +cmpXchgInst: + 'cmpxchg' weak = 'weak'? volatile = 'volatile'? typeValue ',' typeValue ',' typeValue syncScope? + atomicOrdering atomicOrdering (',' align)? ( + ',' metadataAttachment + )*; +atomicRMWInst: + 'atomicrmw' volatile = 'volatile'? atomicOp typeValue ',' typeValue syncScope? atomicOrdering ( + ',' align + )? (',' metadataAttachment)*; +getElementPtrInst: + 'getelementptr' inBounds? type ',' typeValue (',' typeValue)* ( + ',' metadataAttachment + )*; +truncInst: + 'trunc' typeValue 'to' type (',' metadataAttachment)*; +zExtInst: 'zext' typeValue 'to' type ( ',' metadataAttachment)*; +sExtInst: 'sext' typeValue 'to' type ( ',' metadataAttachment)*; +fpTruncInst: + 'fptrunc' typeValue 'to' type (',' metadataAttachment)*; +fpExtInst: + 'fpext' typeValue 'to' type (',' metadataAttachment)*; +fpToUiInst: + 'fptoui' typeValue 'to' type (',' metadataAttachment)*; +fpToSiInst: + 'fptosi' typeValue 'to' type (',' metadataAttachment)*; +uiToFpInst: + 'uitofp' typeValue 'to' type (',' metadataAttachment)*; +siToFpInst: + 'sitofp' typeValue 'to' type (',' metadataAttachment)*; +ptrToIntInst: + 'ptrtoint' typeValue 'to' type (',' metadataAttachment)*; +intToPtrInst: + 'inttoptr' typeValue 'to' type (',' metadataAttachment)*; +bitCastInst: + 'bitcast' typeValue 'to' type (',' metadataAttachment)*; +addrSpaceCastInst: + 'addrspacecast' typeValue 'to' type (',' metadataAttachment)*; +iCmpInst: + 'icmp' iPred typeValue ',' value (',' metadataAttachment)*; +fCmpInst: + 'fcmp' fastMathFlag* fPred typeValue ',' value ( + ',' metadataAttachment + )*; +phiInst: + 'phi' fastMathFlag* type (inc (',' inc)*) ( + ',' metadataAttachment + )*; +selectInst: + 'select' fastMathFlag* typeValue ',' typeValue ',' typeValue ( + ',' metadataAttachment + )*; +freezeInst: 'freeze' typeValue; +callInst: + tail = ('musttail' | 'notail' | 'tail')? 'call' fastMathFlag* callingConv? returnAttribute* + addrSpace? type value '(' args ')' funcAttribute* ( + '[' operandBundle (',' operandBundle)* ']' + )? (',' metadataAttachment)*; +vaargInst: + 'va_arg' typeValue ',' type (',' metadataAttachment)*; +landingPadInst: + 'landingpad' type cleanUp = 'cleanup'? clause* ( + ',' metadataAttachment + )*; +catchPadInst: + 'catchpad' 'within' LocalIdent '[' ( + exceptionArg (',' exceptionArg)* + )? ']' (',' metadataAttachment)*; +cleanupPadInst: + 'cleanuppad' 'within' exceptionPad '[' ( + exceptionArg (',' exceptionArg)* + )? ']' (',' metadataAttachment)*; + +inc: '[' value ',' LocalIdent ']'; + +operandBundle: StringLit '(' (typeValue (',' typeValue)*)? ')'; +clause: clauseType = ('catch' | 'filter') typeValue; + +args: + ellipsis = '...'? + | arg (',' arg)* (',' ellipsis = '...')?; +arg: concreteType paramAttribute* value | metadataType metadata; + +exceptionArg: concreteType value | metadataType metadata; +exceptionPad: noneConst | LocalIdent; + +externalLinkage: 'extern_weak' | 'external'; +internalLinkage: + 'appending' + | 'available_externally' + | 'common' + | 'internal' + | 'linkonce' + | 'linkonce_odr' + | 'private' + | 'weak' + | 'weak_odr'; +linkage: internalLinkage | externalLinkage; +preemption: 'dso_local' | 'dso_preemptable'; +visibility: 'default' | 'hidden' | 'protected'; +dllStorageClass: 'dllexport' | 'dllimport'; +tlsModel: 'initialexec' | 'localdynamic' | 'localexec'; +unnamedAddr: 'local_unnamed_addr' | 'unnamed_addr'; +externallyInitialized: 'externally_initialized'; +immutable: 'constant' | 'global'; +funcAttr: + 'alwaysinline' + | 'argmemonly' + | 'builtin' + | 'cold' + | 'convergent' + | 'disable_sanitizer_instrumentation' + | 'fn_ret_thunk_extern' + | 'hot' + | 'inaccessiblemem_or_argmemonly' + | 'inaccessiblememonly' + | 'inlinehint' + | 'jumptable' + | 'minsize' + | 'mustprogress' + | 'naked' + | 'nobuiltin' + | 'nocallback' + | 'nocf_check' + | 'noduplicate' + | 'nofree' + | 'noimplicitfloat' + | 'noinline' + | 'nomerge' + | 'nonlazybind' + | 'noprofile' + | 'norecurse' + | 'noredzone' + | 'noreturn' + | 'nosanitize_bounds' + | 'nosanitize_coverage' + | 'nosync' + | 'nounwind' + | 'null_pointer_is_valid' + | 'optforfuzzing' + | 'optnone' + | 'optsize' + | 'presplitcoroutine' + | 'readnone' + | 'readonly' + | 'returns_twice' + | 'safestack' + | 'sanitize_address' + | 'sanitize_hwaddress' + | 'sanitize_memory' + | 'sanitize_memtag' + | 'sanitize_thread' + | 'shadowcallstack' + | 'speculatable' + | 'speculative_load_hardening' + | 'ssp' + | 'sspreq' + | 'sspstrong' + | 'strictfp' + | 'willreturn' + | 'writeonly'; +distinct: 'distinct'; +inBounds: 'inbounds'; +returnAttr: + 'inreg' + | 'noalias' + | 'nonnull' + | 'noundef' + | 'signext' + | 'zeroext'; +overflowFlag: 'nsw' | 'nuw'; +iPred: + 'eq' + | 'ne' + | 'sge' + | 'sgt' + | 'sle' + | 'slt' + | 'uge' + | 'ugt' + | 'ule' + | 'ult'; +fPred: + 'false' + | 'oeq' + | 'oge' + | 'ogt' + | 'ole' + | 'olt' + | 'one' + | 'ord' + | 'true' + | 'ueq' + | 'uge' + | 'ugt' + | 'ule' + | 'ult' + | 'une' + | 'uno'; +atomicOrdering: + 'acq_rel' + | 'acquire' + | 'monotonic' + | 'release' + | 'seq_cst' + | 'unordered'; +callingConvEnum: + 'aarch64_sve_vector_pcs' + | 'aarch64_vector_pcs' + | 'amdgpu_cs' + | 'amdgpu_es' + | 'amdgpu_gfx' + | 'amdgpu_gs' + | 'amdgpu_hs' + | 'amdgpu_kernel' + | 'amdgpu_ls' + | 'amdgpu_ps' + | 'amdgpu_vs' + | 'anyregcc' + | 'arm_aapcs_vfpcc' + | 'arm_aapcscc' + | 'arm_apcscc' + | 'avr_intrcc' + | 'avr_signalcc' + | 'ccc' + | 'cfguard_checkcc' + | 'coldcc' + | 'cxx_fast_tlscc' + | 'fastcc' + | 'ghccc' + | 'hhvm_ccc' + | 'hhvmcc' + | 'intel_ocl_bicc' + | 'msp430_intrcc' + | 'preserve_allcc' + | 'preserve_mostcc' + | 'ptx_device' + | 'ptx_kernel' + | 'spir_func' + | 'spir_kernel' + | 'swiftcc' + | 'swifttailcc' + | 'tailcc' + | 'webkit_jscc' + | 'win64cc' + | 'x86_64_sysvcc' + | 'x86_fastcallcc' + | 'x86_intrcc' + | 'x86_regcallcc' + | 'x86_stdcallcc' + | 'x86_thiscallcc' + | 'x86_vectorcallcc'; + +fastMathFlag: + 'afn' + | 'arcp' + | 'contract' + | 'fast' + | 'ninf' + | 'nnan' + | 'nsz' + | 'reassoc'; +atomicOp: + 'add' + | 'and' + | 'fadd' + | 'fmax' + | 'fmin' + | 'fsub' + | 'max' + | 'min' + | 'nand' + | 'or' + | 'sub' + | 'umax' + | 'umin' + | 'xchg' + | 'xor'; +floatKind: + 'half' + | 'bfloat' + | 'float' + | 'double' + | 'x86_fp80' + | 'fp128' + | 'ppc_fp128'; +/*็œ‹ไธๆ‡‚๏ผŒ็›ดๆŽฅๆŠ„่ฟ‡ๆฅ็š„ */ +specializedMDNode: + diBasicType + | diCommonBlock // not in spec as of 2019-12-05 + | diCompileUnit + | diCompositeType + | diDerivedType + | diEnumerator + | diExpression + | diFile + | diGlobalVariable + | diGlobalVariableExpression + | diImportedEntity + | diLabel // not in spec as of 2018-10-14, still not in spec as of 2019-12-05 + | diLexicalBlock + | diLexicalBlockFile + | diLocalVariable + | diLocation + | diMacro + | diMacroFile + | diModule // not in spec as of 2018-02-21, still not in spec as of 2019-12-05 + | diNamespace + | diObjCProperty + | diStringType + | diSubprogram + | diSubrange + | diSubroutineType + | diTemplateTypeParameter + | diTemplateValueParameter + | genericDiNode; // not in spec as of 2018-02-21, still not in spec as of 2019-12-05 + +diBasicType: + '!DIBasicType' '(' (diBasicTypeField (',' diBasicTypeField)*)? ')'; +diCommonBlock: + '!DICommonBlock' '(' ( + diCommonBlockField (',' diCommonBlockField)* + )? ')'; +diCompileUnit: + '!DICompileUnit' '(' ( + diCompileUnitField (',' diCompileUnitField)* + )? ')'; +diCompositeType: + '!DICompositeType' '(' ( + diCompositeTypeField (',' diCompositeTypeField)* + )? ')'; +diCompositeTypeField: + tagField + | nameField + | scopeField + | fileField + | lineField + | baseTypeField + | sizeField + | alignField + | offsetField + | flagsField + | elementsField + | runtimeLangField + | vtableHolderField + | templateParamsField + | identifierField + | discriminatorField + | dataLocationField + | associatedField + | allocatedField + | rankField + | annotationsField; +diDerivedType: + '!DIDerivedType' '(' ( + diDerivedTypeField (',' diDerivedTypeField)* + )? ')'; +diDerivedTypeField: + tagField + | nameField + | scopeField + | fileField + | lineField + | baseTypeField + | sizeField + | alignField + | offsetField + | flagsField + | extraDataField + | dwarfAddressSpaceField + | annotationsField; +diEnumerator: + '!DIEnumerator' '(' ( + diEnumeratorField (',' diEnumeratorField)* + )? ')'; +diEnumeratorField: nameField | valueIntField | isUnsignedField; +diFile: '!DIFile' '(' (diFileField (',' diFileField)*)? ')'; +diFileField: + filenameField + | directoryField + | checksumkindField + | checksumField + | sourceField; +diGlobalVariable: + '!DIGlobalVariable' '(' ( + diGlobalVariableField (',' diGlobalVariableField)* + )? ')'; +diGlobalVariableField: + nameField + | scopeField + | linkageNameField + | fileField + | lineField + | typeField + | isLocalField + | isDefinitionField + | templateParamsField + | declarationField + | alignField + | annotationsField; +diGlobalVariableExpression: + '!DIGlobalVariableExpression' '(' ( + diGlobalVariableExpressionField ( + ',' diGlobalVariableExpressionField + )* + )? ')'; +diGlobalVariableExpressionField: varField | exprField; +diImportedEntity: + '!DIImportedEntity' '(' ( + diImportedEntityField (',' diImportedEntityField)* + )? ')'; +diImportedEntityField: + tagField + | scopeField + | entityField + | fileField + | lineField + | nameField + | elementsField; + +diLabel: '!DILabel' '(' (diLabelField (',' diLabelField)*)? ')'; +diLabelField: scopeField | nameField | fileField | lineField; +diLexicalBlock: + '!DILexicalBlock' '(' ( + diLexicalBlockField (',' diLexicalBlockField)* + )? ')'; +diLexicalBlockField: + scopeField + | fileField + | lineField + | columnField; +diLexicalBlockFile: + '!DILexicalBlockFile' '(' ( + diLexicalBlockFileField (',' diLexicalBlockFileField)* + )? ')'; +diLexicalBlockFileField: + scopeField + | fileField + | discriminatorIntField; +diLocalVariable: + '!DILocalVariable' '(' ( + diLocalVariableField (',' diLocalVariableField)* + )? ')'; +diLocalVariableField: + scopeField + | nameField + | argField + | fileField + | lineField + | typeField + | flagsField + | alignField + | annotationsField; +diLocation: + '!DILocation' '(' (diLocationField (',' diLocationField)*)? ')'; +diLocationField: + lineField + | columnField + | scopeField + | inlinedAtField + | isImplicitCodeField; +diMacro: '!DIMacro' '(' (diMacroField (',' diMacroField)*)? ')'; +diMacroField: + typeMacinfoField + | lineField + | nameField + | valueStringField; +diMacroFile: + '!DIMacroFile' '(' (diMacroFileField (',' diMacroFileField)*)? ')'; +diMacroFileField: + typeMacinfoField + | lineField + | fileField + | nodesField; +diModule: + '!DIModule' '(' (diModuleField (',' diModuleField)*)? ')'; +diModuleField: + scopeField + | nameField + | configMacrosField + | includePathField + | apiNotesField + | fileField + | lineField + | isDeclField; +diNamespace: + '!DINamespace' '(' (diNamespaceField (',' diNamespaceField)*)? ')'; +diNamespaceField: scopeField | nameField | exportSymbolsField; +diObjCProperty: + '!DIObjCProperty' '(' ( + diObjCPropertyField (',' diObjCPropertyField)* + )? ')'; +diObjCPropertyField: + nameField + | fileField + | lineField + | setterField + | getterField + | attributesField + | typeField; +diStringType: + '!DIStringType' '(' ( + diStringTypeField (',' diStringTypeField)* + )? ')'; +diStringTypeField: + tagField + | nameField + | stringLengthField + | stringLengthExpressionField + | stringLocationExpressionField + | sizeField + | alignField + | encodingField; +diSubprogram: + '!DISubprogram' '(' ( + diSubprogramField (',' diSubprogramField)* + )? ')'; +diSubprogramField: + scopeField + | nameField + | linkageNameField + | fileField + | lineField + | typeField + | isLocalField + | isDefinitionField + | scopeLineField + | containingTypeField + | virtualityField + | virtualIndexField + | thisAdjustmentField + | flagsField + | spFlagsField + | isOptimizedField + | unitField + | templateParamsField + | declarationField + | retainedNodesField + | thrownTypesField + | annotationsField + | targetFuncNameField; +diSubrange: + '!DISubrange' '(' (diSubrangeField (',' diSubrangeField)*)? ')'; +diSubrangeField: + countField + | lowerBoundField + | upperBoundField + | strideField; +diSubroutineType: + '!DISubroutineType' '(' ( + diSubroutineTypeField (',' diSubroutineTypeField)* + )? ')'; +diTemplateTypeParameter: + '!DITemplateTypeParameter' '(' ( + diTemplateTypeParameterField ( + ',' diTemplateTypeParameterField + )* + )? ')'; +diTemplateValueParameter: + '!DITemplateValueParameter' '(' ( + diTemplateValueParameterField ( + ',' diTemplateValueParameterField + ) + )? ')'; +genericDiNode: + '!GenericDINode' '(' ( + genericDINodeField (',' genericDINodeField)* + )? ')'; + +diTemplateTypeParameterField: + nameField + | typeField + | defaultedField; +diCompileUnitField: + languageField + | fileField + | producerField + | isOptimizedField + | flagsStringField + | runtimeVersionField + | splitDebugFilenameField + | emissionKindField + | enumsField + | retainedTypesField + | globalsField + | importsField + | macrosField + | dwoIdField + | splitDebugInliningField + | debugInfoForProfilingField + | nameTableKindField + | rangesBaseAddressField + | sysrootField + | sdkField; +diCommonBlockField: + scopeField + | declarationField + | nameField + | fileField + | lineField; +diBasicTypeField: + tagField + | nameField + | sizeField + | alignField + | encodingField + | flagsField; +genericDINodeField: tagField | headerField | operandsField; +tagField: 'tag:' DwarfTag; +headerField: 'header:' StringLit; +operandsField: 'operands:' '{' (mdField (',' mdField)*)? '}'; +diTemplateValueParameterField: + tagField + | nameField + | typeField + | defaultedField + | valueField; +nameField: 'name:' StringLit; +typeField: 'type:' mdField; +defaultedField: 'defaulted:' boolConst; +valueField: 'value:' mdField; +mdField: nullConst | metadata; +diSubroutineTypeField: flagsField | ccField | typesField; +flagsField: 'flags:' diFlags; +diFlags: DiFlag ('|' DiFlag)*; +ccField: 'cc:' DwarfCc | IntLit; +alignField: 'align:' IntLit; +allocatedField: 'allocated:' mdField; +annotationsField: 'annotations:' mdField; +argField: 'arg:' IntLit; +associatedField: 'associated:' mdField; +attributesField: 'attributes:' IntLit; +baseTypeField: 'baseType:' mdField; +checksumField: 'checksum:' StringLit; +checksumkindField: 'checksumkind:' ChecksumKind; +columnField: 'column:' IntLit; +configMacrosField: 'configMacros:' StringLit; +containingTypeField: 'containingType:' mdField; +countField: 'count:' mdFieldOrInt; +debugInfoForProfilingField: 'debugInfoForProfiling:' boolConst; +declarationField: 'declaration:' mdField; +directoryField: 'directory:' StringLit; +discriminatorField: 'discriminator:' mdField; +dataLocationField: 'dataLocation:' mdField; +discriminatorIntField: 'discriminator:' IntLit; +dwarfAddressSpaceField: 'dwarfAddressSpace:' IntLit; +dwoIdField: 'dwoId:' IntLit; +elementsField: 'elements:' mdField; +emissionKindField: + 'emissionKind:' emissionKind = ( + 'DebugDirectivesOnly' + | 'FullDebug' + | 'LineTablesOnly' + | 'NoDebug' + ); +encodingField: 'encoding:' (IntLit | DwarfAttEncoding); +entityField: 'entity:' mdField; +enumsField: 'enums:' mdField; +exportSymbolsField: 'exportSymbols:' boolConst; +exprField: 'expr:' mdField; +extraDataField: 'extraData:' mdField; +fileField: 'file:' mdField; +filenameField: 'filename:' StringLit; +flagsStringField: 'flags:' StringLit; +getterField: 'getter:' StringLit; +globalsField: 'globals:' mdField; +identifierField: 'identifier:' StringLit; +importsField: 'imports:' mdField; +includePathField: 'includePath:' StringLit; +inlinedAtField: 'inlinedAt:' mdField; +isDeclField: 'isDecl:' boolConst; +isDefinitionField: 'isDefinition:' boolConst; +isImplicitCodeField: 'isImplicitCode:' boolConst; +isLocalField: 'isLocal:' boolConst; +isOptimizedField: 'isOptimized:' boolConst; +isUnsignedField: 'isUnsigned:' boolConst; +apiNotesField: 'apinotes:' StringLit; +languageField: 'language:' DwarfLang; +lineField: 'line:' IntLit; +linkageNameField: 'linkageName:' StringLit; +lowerBoundField: 'lowerBound:' mdFieldOrInt; +macrosField: 'macros:' mdField; +nameTableKindField: + 'nameTableKind:' nameTableKind = ('GNU' | 'None' | 'Default'); +nodesField: 'nodes:' mdField; +offsetField: + // TODO: rename OffsetField= attribute to Offset= when inspirer/textmapper#13 is resolved + 'offset:' IntLit; +producerField: 'producer:' StringLit; +rangesBaseAddressField: 'rangesBaseAddress:' boolConst; +rankField: 'rank:' mdFieldOrInt; +retainedNodesField: 'retainedNodes:' mdField; +retainedTypesField: 'retainedTypes:' mdField; +runtimeLangField: 'runtimeLang:' DwarfLang; +runtimeVersionField: 'runtimeVersion:' IntLit; +scopeField: 'scope:' mdField; +scopeLineField: 'scopeLine:' IntLit; +sdkField: 'sdk:' StringLit; +setterField: 'setter:' StringLit; +sizeField: 'size:' IntLit; +sourceField: 'source:' StringLit; +spFlagsField: 'spFlags:' (diSPFlag ('|' diSPFlag)*); +splitDebugFilenameField: 'splitDebugFilename:' StringLit; +splitDebugInliningField: 'splitDebugInlining:' boolConst; +strideField: 'stride:' mdFieldOrInt; +stringLengthField: 'stringLength:' mdField; +stringLengthExpressionField: 'stringLengthExpression:' mdField; +stringLocationExpressionField: + 'stringLocationExpression:' mdField; +sysrootField: 'sysroot:' StringLit; +targetFuncNameField: 'targetFuncName:' StringLit; +templateParamsField: 'templateParams:' mdField; +thisAdjustmentField: 'thisAdjustment:' IntLit; +thrownTypesField: 'thrownTypes:' mdField; +typeMacinfoField: 'type:' DwarfMacinfo; +typesField: 'types:' mdField; +unitField: 'unit:' mdField; +upperBoundField: 'upperBound:' mdFieldOrInt; +valueIntField: 'value:' IntLit; +valueStringField: 'value:' StringLit; +varField: 'var:' mdField; +virtualIndexField: 'virtualIndex:' IntLit; +virtualityField: 'virtuality:' DwarfVirtuality; +vtableHolderField: 'vtableHolder:' mdField; + +fragment AsciiLetter: [A-Za-z]; +fragment Letter: AsciiLetter | [-$._]; +fragment EscapeLetter: Letter | '\\'; +fragment DecimalDigit: [0-9]; +fragment HexDigit: [A-Fa-f] | DecimalDigit; +fragment Decimals: DecimalDigit+; +fragment Name: Letter (Letter | DecimalDigit)*; +fragment EscapeName: + EscapeLetter (EscapeLetter | DecimalDigit)*; +fragment Id: Decimals; +fragment IntHexLit: [us] '0x' HexDigit+; +// ๆตฎ็‚นๅž‹ๅธธ้‡ +fragment Sign: [+-]; +fragment FracLit: Sign? Decimals '.' DecimalDigit*; +fragment SciLit: FracLit [eE] Sign? Decimals; +/* + HexFPConstant 0x{_hex_digit}+ // 16 hex digits + HexFP80Constant 0xK{_hex_digit}+ // 20 hex digits + HexFP128Constant 0xL{_hex_digit}+ // 32 hex digits + HexPPC128Constant 0xM{_hex_digit}+ // 32 hex + digits + HexHalfConstant 0xH{_hex_digit}+ // 4 hex digits + HexBFloatConstant 0xR{_hex_digit}+ // 4 + hex digits + */ +fragment FloatHexLit: '0x' [KLMHR]? HexDigit+; +fragment GlobalName: '@' (Name | QuotedString); +fragment GlobalId: '@' Id; +fragment LocalName: '%' (Name | QuotedString); +fragment LocalId: '%' Id; +fragment QuotedString: '"' (~["\r\n])* '"'; +Comment: ';' .*? '\r'? '\n' -> channel(HIDDEN); +WhiteSpace: [ \t\n\r]+ -> skip; +IntLit: '-'? DecimalDigit+ | IntHexLit; +FloatLit: FracLit | SciLit | FloatHexLit; +StringLit: QuotedString; +GlobalIdent: GlobalName | GlobalId; +LocalIdent: LocalName | LocalId; +LabelIdent: (Letter | DecimalDigit)+ ':' | QuotedString ':'; +AttrGroupId: '#' Id; +ComdatName: '$' (Name | QuotedString); +MetadataName: '!' EscapeName; +MetadataId: '!' Id; +IntType: 'i' DecimalDigit+; +DwarfTag: 'DW_TAG_' (AsciiLetter | DecimalDigit | '_')*; +DwarfAttEncoding: 'DW_ATE_' (AsciiLetter | DecimalDigit | '_')*; +DiFlag: 'DIFlag' (AsciiLetter | DecimalDigit | '_')*; +DispFlag: 'DISPFlag' (AsciiLetter | DecimalDigit | '_')*; +DwarfLang: 'DW_LANG_' (AsciiLetter | DecimalDigit | '_')*; +DwarfCc: 'DW_CC_' (AsciiLetter | DecimalDigit | '_')*; +ChecksumKind: 'CSK_' (AsciiLetter | DecimalDigit | '_')*; +DwarfVirtuality: + 'DW_VIRTUALITY_' (AsciiLetter | DecimalDigit | '_')*; +DwarfMacinfo: 'DW_MACINFO_' (AsciiLetter | DecimalDigit | '_')*; +DwarfOp: 'DW_OP_' (AsciiLetter | DecimalDigit | '_')*; diff --git a/languages/llvmir/src/main/java/de/jplag/llvmir/LLVMIRLanguage.java b/languages/llvmir/src/main/java/de/jplag/llvmir/LLVMIRLanguage.java new file mode 100644 index 000000000..846a047e6 --- /dev/null +++ b/languages/llvmir/src/main/java/de/jplag/llvmir/LLVMIRLanguage.java @@ -0,0 +1,42 @@ +package de.jplag.llvmir; + +import org.kohsuke.MetaInfServices; + +import de.jplag.Language; +import de.jplag.antlr.AbstractAntlrLanguage; + +/** + * The entry point for the ANTLR parser based LLVM IR language module. + */ +@MetaInfServices(Language.class) +public class LLVMIRLanguage extends AbstractAntlrLanguage { + + private static final String NAME = "LLVMIR Parser"; + private static final String IDENTIFIER = "llvmir"; + private static final int DEFAULT_MIN_TOKEN_MATCH = 70; + private static final String[] FILE_EXTENSIONS = {".ll"}; + + public LLVMIRLanguage() { + super(new LLVMIRParserAdapter()); + } + + @Override + public String[] suffixes() { + return FILE_EXTENSIONS; + } + + @Override + public String getName() { + return NAME; + } + + @Override + public String getIdentifier() { + return IDENTIFIER; + } + + @Override + public int minimumTokenMatch() { + return DEFAULT_MIN_TOKEN_MATCH; + } +} diff --git a/languages/llvmir/src/main/java/de/jplag/llvmir/LLVMIRListener.java b/languages/llvmir/src/main/java/de/jplag/llvmir/LLVMIRListener.java new file mode 100644 index 000000000..24e70a9ca --- /dev/null +++ b/languages/llvmir/src/main/java/de/jplag/llvmir/LLVMIRListener.java @@ -0,0 +1,232 @@ +package de.jplag.llvmir; + +import static de.jplag.llvmir.LLVMIRTokenType.*; +import static de.jplag.llvmir.grammar.LLVMIRParser.AShrExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.AShrInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.AddExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.AddInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.AddrSpaceCastExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.AddrSpaceCastInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.AllocaInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.AndExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.AndInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.ArrayConstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.AtomicOrderingContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.AtomicRMWInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.BasicBlockContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.BitCastExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.BitCastInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.BrTermContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.CallBrTermContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.CallInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.Case_Context; +import static de.jplag.llvmir.grammar.LLVMIRParser.CatchPadInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.CatchRetTermContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.CatchSwitchTermContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.ClauseContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.CleanupPadInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.CleanupRetTermContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.CmpXchgInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.CondBrTermContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.ExtractElementExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.ExtractElementInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.ExtractValueInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.FAddInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.FCmpExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.FCmpInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.FDivInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.FMulInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.FRemInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.FSubInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.FenceInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.FpExtExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.FpExtInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.FpToSiExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.FpToSiInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.FpToUiExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.FpToUiInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.FpTruncExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.FpTruncInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.FuncBodyContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.FuncDeclContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.FuncDefContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.GetElementPtrExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.GetElementPtrInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.GlobalDeclContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.GlobalDefContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.ICmpExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.ICmpInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.IndirectBrTermContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.InlineAsmContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.InsertElementExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.InsertElementInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.InsertValueInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.IntToPtrExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.IntToPtrInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.InvokeTermContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.LShrExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.LShrInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.LandingPadInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.LoadInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.ModuleAsmContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.MulExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.MulInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.OrExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.OrInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.PhiInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.PtrToIntExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.PtrToIntInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.ResumeTermContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.RetTermContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.SDivInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.SExtExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.SExtInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.SRemInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.SelectExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.SelectInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.ShlExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.ShlInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.ShuffleVectorExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.ShuffleVectorInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.SiToFpExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.SiToFpInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.SourceFilenameContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.StoreInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.StructConstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.SubExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.SubInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.SwitchTermContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.TruncExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.TruncInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.TypeDefContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.UDivInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.URemInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.UiToFpExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.UiToFpInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.VaargInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.VectorConstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.XorExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.XorInstContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.ZExtExprContext; +import static de.jplag.llvmir.grammar.LLVMIRParser.ZExtInstContext; + +import de.jplag.antlr.AbstractAntlrListener; + +/** + * Extracts tokens from the ANTLR parse tree. The token abstraction includes nesting tokens for functions and basic + * blocks and separate tokens for different elements. These include binary and bitwise instructions, memory operations, + * terminator instructions, conversions, global variables, type definitions, constants, and others. + */ +class LLVMIRListener extends AbstractAntlrListener { + + LLVMIRListener() { + visit(SourceFilenameContext.class).map(FILENAME); + visit(ModuleAsmContext.class).map(ASSEMBLY); + visit(TypeDefContext.class).map(TYPE_DEFINITION); + visit(GlobalDeclContext.class).map(GLOBAL_VARIABLE); + visit(GlobalDefContext.class).map(GLOBAL_VARIABLE); + visit(FuncDeclContext.class).map(FUNCTION_DECLARATION); + visit(FuncDefContext.class).map(FUNCTION_DEFINITION); + visit(FuncBodyContext.class).map(FUNCTION_BODY_BEGIN, FUNCTION_BODY_END); + visit(BasicBlockContext.class).map(BASIC_BLOCK_BEGIN, BASIC_BLOCK_END); + visit(RetTermContext.class).map(RETURN); + visit(BrTermContext.class).map(BRANCH); + visit(CondBrTermContext.class).map(CONDITIONAL_BRANCH); + visit(SwitchTermContext.class).map(SWITCH); + visit(IndirectBrTermContext.class).map(BRANCH); + visit(ResumeTermContext.class).map(RESUME); + visit(CatchRetTermContext.class).map(CATCH_RETURN); + visit(CleanupRetTermContext.class).map(CLEAN_UP_RETURN); + visit(InvokeTermContext.class).map(INVOKE); + visit(CallBrTermContext.class).map(CALL_BRANCH); + visit(CatchSwitchTermContext.class).map(CATCH_SWITCH); + visit(Case_Context.class).map(CASE); + visit(StructConstContext.class).map(STRUCTURE); + visit(ArrayConstContext.class).map(ARRAY); + visit(VectorConstContext.class).map(VECTOR); + visit(InlineAsmContext.class).map(ASSEMBLY); + visit(BitCastExprContext.class).map(BITCAST); + visit(GetElementPtrExprContext.class).map(GET_ELEMENT_POINTER); + visit(AddrSpaceCastExprContext.class).map(CONVERSION); + visit(IntToPtrExprContext.class).map(CONVERSION); + visit(ICmpExprContext.class).map(COMPARISON); + visit(FCmpExprContext.class).map(COMPARISON); + visit(SelectExprContext.class).map(SELECT); + visit(TruncExprContext.class).map(CONVERSION); + visit(ZExtExprContext.class).map(CONVERSION); + visit(SExtExprContext.class).map(CONVERSION); + visit(FpTruncExprContext.class).map(CONVERSION); + visit(FpExtExprContext.class).map(CONVERSION); + visit(FpToUiExprContext.class).map(CONVERSION); + visit(FpToSiExprContext.class).map(CONVERSION); + visit(UiToFpExprContext.class).map(CONVERSION); + visit(SiToFpExprContext.class).map(CONVERSION); + visit(PtrToIntExprContext.class).map(CONVERSION); + visit(ExtractElementExprContext.class).map(EXTRACT_ELEMENT); + visit(InsertElementExprContext.class).map(INSERT_ELEMENT); + visit(ShuffleVectorExprContext.class).map(SHUFFLE_VECTOR); + visit(ShlExprContext.class).map(SHIFT); + visit(LShrExprContext.class).map(SHIFT); + visit(AShrExprContext.class).map(SHIFT); + visit(AndExprContext.class).map(AND); + visit(OrExprContext.class).map(OR); + visit(XorExprContext.class).map(XOR); + visit(AddExprContext.class).map(ADDITION); + visit(SubExprContext.class).map(SUBTRACTION); + visit(MulExprContext.class).map(MULTIPLICATION); + visit(StoreInstContext.class).map(STORE); + visit(FenceInstContext.class).map(FENCE); + visit(AddInstContext.class).map(ADDITION); + visit(FAddInstContext.class).map(ADDITION); + visit(SubInstContext.class).map(SUBTRACTION); + visit(FSubInstContext.class).map(SUBTRACTION); + visit(MulInstContext.class).map(MULTIPLICATION); + visit(FMulInstContext.class).map(MULTIPLICATION); + visit(UDivInstContext.class).map(DIVISION); + visit(SDivInstContext.class).map(DIVISION); + visit(FDivInstContext.class).map(DIVISION); + visit(URemInstContext.class).map(REMAINDER); + visit(SRemInstContext.class).map(REMAINDER); + visit(FRemInstContext.class).map(REMAINDER); + visit(ShlInstContext.class).map(SHIFT); + visit(LShrInstContext.class).map(SHIFT); + visit(AShrInstContext.class).map(SHIFT); + visit(AndInstContext.class).map(AND); + visit(OrInstContext.class).map(OR); + visit(XorInstContext.class).map(XOR); + visit(ExtractElementInstContext.class).map(EXTRACT_ELEMENT); + visit(InsertElementInstContext.class).map(INSERT_ELEMENT); + visit(ShuffleVectorInstContext.class).map(SHUFFLE_VECTOR); + visit(ExtractValueInstContext.class).map(EXTRACT_VALUE); + visit(InsertValueInstContext.class).map(INSERT_VALUE); + visit(AllocaInstContext.class).map(ALLOCATION); + visit(LoadInstContext.class).map(LOAD); + visit(CmpXchgInstContext.class).map(COMPARE_EXCHANGE); + visit(AtomicRMWInstContext.class).map(ATOMIC_READ_MODIFY_WRITE); + visit(GetElementPtrInstContext.class).map(GET_ELEMENT_POINTER); + visit(TruncInstContext.class).map(CONVERSION); + visit(ZExtInstContext.class).map(CONVERSION); + visit(SExtInstContext.class).map(CONVERSION); + visit(FpTruncInstContext.class).map(CONVERSION); + visit(FpExtInstContext.class).map(CONVERSION); + visit(FpToUiInstContext.class).map(CONVERSION); + visit(FpToSiInstContext.class).map(CONVERSION); + visit(UiToFpInstContext.class).map(CONVERSION); + visit(SiToFpInstContext.class).map(CONVERSION); + visit(PtrToIntInstContext.class).map(CONVERSION); + visit(IntToPtrInstContext.class).map(CONVERSION); + visit(BitCastInstContext.class).map(BITCAST); + visit(AddrSpaceCastInstContext.class).map(CONVERSION); + visit(ICmpInstContext.class).map(COMPARISON); + visit(FCmpInstContext.class).map(COMPARISON); + visit(PhiInstContext.class).map(PHI); + visit(SelectInstContext.class).map(SELECT); + visit(CallInstContext.class).map(CALL); + visit(VaargInstContext.class).map(VARIABLE_ARGUMENT); + visit(LandingPadInstContext.class).map(LANDING_PAD); + visit(CatchPadInstContext.class).map(CATCH_PAD); + visit(CleanupPadInstContext.class).map(CLEAN_UP_PAD); + visit(ClauseContext.class).map(CLAUSE); + visit(AtomicOrderingContext.class).map(ATOMIC_ORDERING); + } +} diff --git a/languages/llvmir/src/main/java/de/jplag/llvmir/LLVMIRParserAdapter.java b/languages/llvmir/src/main/java/de/jplag/llvmir/LLVMIRParserAdapter.java new file mode 100644 index 000000000..edbe94148 --- /dev/null +++ b/languages/llvmir/src/main/java/de/jplag/llvmir/LLVMIRParserAdapter.java @@ -0,0 +1,36 @@ +package de.jplag.llvmir; + +import org.antlr.v4.runtime.*; + +import de.jplag.AbstractParser; +import de.jplag.antlr.AbstractAntlrListener; +import de.jplag.antlr.AbstractAntlrParserAdapter; +import de.jplag.llvmir.grammar.LLVMIRLexer; +import de.jplag.llvmir.grammar.LLVMIRParser; + +/** + * The adapter between {@link AbstractParser} and the ANTLR based parser of this language module. + */ +public class LLVMIRParserAdapter extends AbstractAntlrParserAdapter { + private static final LLVMIRListener listener = new LLVMIRListener(); + + @Override + protected Lexer createLexer(CharStream input) { + return new LLVMIRLexer(input); + } + + @Override + protected LLVMIRParser createParser(CommonTokenStream tokenStream) { + return new LLVMIRParser(tokenStream); + } + + @Override + protected ParserRuleContext getEntryContext(LLVMIRParser parser) { + return parser.compilationUnit(); + } + + @Override + protected AbstractAntlrListener getListener() { + return listener; + } +} diff --git a/languages/llvmir/src/main/java/de/jplag/llvmir/LLVMIRTokenType.java b/languages/llvmir/src/main/java/de/jplag/llvmir/LLVMIRTokenType.java new file mode 100644 index 000000000..0935fa4cc --- /dev/null +++ b/languages/llvmir/src/main/java/de/jplag/llvmir/LLVMIRTokenType.java @@ -0,0 +1,99 @@ +package de.jplag.llvmir; + +import de.jplag.TokenType; + +/** + * LLVM IR token types extracted by this language module. + */ +public enum LLVMIRTokenType implements TokenType { + + FILENAME("FILENAME"), + + // Functions + FUNCTION_BODY_BEGIN("FUNC{"), + FUNCTION_BODY_END("}FUNC"), + BASIC_BLOCK_BEGIN("BLOCK{"), + BASIC_BLOCK_END("}BLOCK"), + FUNCTION_DECLARATION("FUNC_DECL"), + FUNCTION_DEFINITION("FUNC_DEF"), + + GLOBAL_VARIABLE("GLOB_VAR"), + ASSEMBLY("ASM"), + TYPE_DEFINITION("TYPE_DEF"), + + // Constants + STRUCTURE("STRUCT"), + ARRAY("ARR"), + VECTOR("VEC"), + + // Terminator Instructions + RETURN("RET"), + BRANCH("BR"), + SWITCH("SWITCH"), + CASE("CASE"), + CONDITIONAL_BRANCH("COND_BR"), + INVOKE("INVOKE"), + CALL_BRANCH("CALL_BR"), + RESUME("RESUME"), + CATCH_SWITCH("CATCH_SWITCH"), + CATCH_RETURN("CATCH_RET"), + CLEAN_UP_RETURN("CLEAN_UP_RET"), + + // Binary Operations + ADDITION("ADD"), + SUBTRACTION("SUB"), + MULTIPLICATION("MUL"), + DIVISION("DIV"), + REMAINDER("REM"), + + // Bitwise instruction + SHIFT("SHIFT"), + AND("AND"), + OR("OR"), + XOR("XOR"), + + // Vector operations + EXTRACT_ELEMENT("EXTRACT_ELEM"), + INSERT_ELEMENT("INSERT_ELEM"), + SHUFFLE_VECTOR("SHUFFLE_VEC"), + + // Aggregate Operations + EXTRACT_VALUE("EXTRACT_VAL"), + INSERT_VALUE("INSERT_VAL"), + + // Memory Operations + ALLOCATION("ALLOC"), + LOAD("LOAD"), + STORE("STORE"), + FENCE("FENCE"), + COMPARE_EXCHANGE("CMP_XCHG"), + ATOMIC_READ_MODIFY_WRITE("ATOMIC_RMW"), + ATOMIC_ORDERING("ATOMIC"), + GET_ELEMENT_POINTER("GET_ELEMENT_PTR"), + + // Conversion Operations + BITCAST("BITCAST"), + CONVERSION("CONV"), + + // Other Operations + COMPARISON("COMP"), + PHI("PHI"), + SELECT("SELECT"), + CALL("CALL"), + VARIABLE_ARGUMENT("VA_ARG"), + LANDING_PAD("LANDING_PAD"), + CLAUSE("CLAUSE"), + CATCH_PAD("CATCH_PAD"), + CLEAN_UP_PAD("CLEAN_UP_PAD"); + + private final String description; + + LLVMIRTokenType(String description) { + this.description = description; + } + + @Override + public String getDescription() { + return description; + } +} diff --git a/languages/llvmir/src/test/java/de/jplag/llvmir/LLVMIRLanguageTest.java b/languages/llvmir/src/test/java/de/jplag/llvmir/LLVMIRLanguageTest.java new file mode 100644 index 000000000..b34956af9 --- /dev/null +++ b/languages/llvmir/src/test/java/de/jplag/llvmir/LLVMIRLanguageTest.java @@ -0,0 +1,42 @@ +package de.jplag.llvmir; + +import static de.jplag.llvmir.LLVMIRTokenType.*; + +import java.util.Arrays; +import java.util.List; + +import de.jplag.testutils.LanguageModuleTest; +import de.jplag.testutils.datacollector.TestDataCollector; +import de.jplag.testutils.datacollector.TestSourceIgnoredLinesCollector; + +/** + * Provides tests for the llvmir language module + */ +class LLVMIRLanguageTest extends LanguageModuleTest { + public LLVMIRLanguageTest() { + super(new LLVMIRLanguage(), LLVMIRTokenType.class); + } + + @Override + protected void collectTestData(TestDataCollector collector) { + List missingTokens = List.of(CATCH_SWITCH, CATCH_RETURN, CLEAN_UP_RETURN, CATCH_PAD, CLEAN_UP_PAD); + LLVMIRTokenType[] expectedTokens = Arrays.stream(LLVMIRTokenType.values()).filter(it -> !missingTokens.contains(it)) + .toArray(LLVMIRTokenType[]::new); + + collector.testFile("Complete.ll").testSourceCoverage().testContainedTokens(expectedTokens); + + // Finding an example for the new exception handling instructions was difficult. + // Therefore, the NewExceptionHandling.ll file can only be parsed and not executed. + collector.testFile("NewExceptionHandling.ll").testSourceCoverage().testContainedTokens(CATCH_SWITCH, CATCH_RETURN, CLEAN_UP_RETURN, CATCH_PAD, + CLEAN_UP_PAD); + + } + + @Override + protected void configureIgnoredLines(TestSourceIgnoredLinesCollector collector) { + collector.ignoreLinesByPrefix(";"); + collector.ignoreLinesByPrefix("target datalayout"); + collector.ignoreLinesByPrefix("target triple"); + collector.ignoreLinesByPrefix("unreachable"); + } +} \ No newline at end of file diff --git a/languages/llvmir/src/test/resources/de/jplag/llvmir/Complete.ll b/languages/llvmir/src/test/resources/de/jplag/llvmir/Complete.ll new file mode 100644 index 000000000..2ccaf60ee --- /dev/null +++ b/languages/llvmir/src/test/resources/de/jplag/llvmir/Complete.ll @@ -0,0 +1,161 @@ +; ModuleID = 'Complete.c' +source_filename = "Complete.c" +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" +target triple = "arm64-apple-macosx13.0.0" + +@Global_Var = private unnamed_addr constant [14 x i8] c"Hello World!\0A\00", align 1 +@struct.const = private constant {i32, double} {i32 4, double 8.12} + +%struct.Struct = type { i32 } +@_ZTIi = external constant ptr + +; Function Attrs: noinline nounwind optnone ssp uwtable +define i32 @main() #0 { + %1 = alloca i32, align 4 + %2 = alloca i32, align 4 + %3 = alloca i32, align 4 + %4 = alloca float, align 4 + %5 = alloca %struct.Struct, align 4 + store i32 0, ptr %1, align 4 + store i32 4, ptr %2, align 4 + %6 = load i32, ptr %2, align 4 + %7 = add nsw i32 5, %6 + store i32 %7, ptr %3, align 4 + %8 = load i32, ptr %2, align 4 + %9 = sub nsw i32 5, %8 + store i32 %9, ptr %3, align 4 + %10 = load i32, ptr %2, align 4 + %11 = mul nsw i32 5, %10 + store i32 %11, ptr %3, align 4 + %12 = load i32, ptr %2, align 4 + %13 = sdiv i32 5, %12 + %14 = sitofp i32 %13 to float + store float %14, ptr %4, align 4 + %15 = load i32, ptr %2, align 4 + %16 = srem i32 5, %15 + store i32 %16, ptr %3, align 4 + %17 = load i32, ptr %2, align 4 + %18 = shl i32 %17, 5 + store i32 %18, ptr %3, align 4 + %19 = load i32, ptr %2, align 4 + %20 = and i32 %19, 5 + store i32 %20, ptr %3, align 4 + %21 = load i32, ptr %2, align 4 + %22 = or i32 %21, 5 + store i32 %22, ptr %3, align 4 + %23 = load i32, ptr %2, align 4 + %24 = xor i32 %23, 5 + store i32 %24, ptr %3, align 4 + %25 = call i32 (ptr, ...) @printf(ptr noundef @Global_Var) + %cast = bitcast i8 255 to i8 + br label %vectors + +vectors: + %26 = call i32 @vector(<4 x i32> , <4 x i32> ) + switch i32 %26, label %vectors [ i32 10, label %aggregates + i32 1, label %vectors + i32 2, label %vectors ] + +aggregates: + %struc = insertvalue {i32} undef, i32 1, 0 + %27 = extractvalue {i32} %struc, 0 + callbr void asm "", "r,!i"(i32 0) to label %memory [label %aggregates] + +memory: + fence acquire + br label %entry + +entry: + %28 = getelementptr inbounds %struct.Struct, ptr %5, i32 0, i32 0 + %tmp = va_arg ptr %28, i32 + store i32 1, ptr %28, align 4 + %old = atomicrmw add ptr %28, i32 1 acquire + %orig = load atomic i32, ptr %28 unordered, align 4 + br label %loop + +loop: + %cmp = phi i32 [ %orig, %entry ], [%value_loaded, %loop] + %squared = mul i32 %cmp, %cmp + %val_success = cmpxchg ptr %28, i32 %cmp, i32 %squared acq_rel monotonic + %value_loaded = extractvalue { i32, i1 } %val_success, 0 + %success = extractvalue { i32, i1 } %val_success, 1 + br i1 %success, label %done, label %loop + +done: + %false = icmp eq i32 4, 5 + %first = select i1 true, i8 17, i8 42 + call void @Exception() + ret i32 0 +} + +define i32 @vector(<4 x i32> %v1, <4 x i32> %v2) { + %vec = shufflevector <4 x i32> %v1, <4 x i32> %v2, <4 x i32> + %vec_ins = insertelement <4 x i32> %vec, i32 10, i32 0 + %elem = extractelement <4 x i32> %vec_ins, i32 0 + ret i32 %elem +} + +; Function Attrs: mustprogress noinline norecurse optnone ssp uwtable +define noundef i32 @Exception() personality ptr @__gxx_personality_v0 { + %1 = alloca i32, align 4 + %2 = alloca ptr, align 8 + %3 = alloca i32, align 4 + %4 = alloca i32, align 4 + store i32 0, ptr %1, align 4 + %5 = call ptr @__cxa_allocate_exception(i64 4) + store i32 5, ptr %5, align 16 + invoke void @__cxa_throw(ptr %5, ptr @_ZTIi, ptr null) to label %25 unwind label %6 + +6: + %7 = landingpad { ptr, i32 } + catch ptr @_ZTIi + %8 = extractvalue { ptr, i32 } %7, 0 + store ptr %8, ptr %2, align 8 + %9 = extractvalue { ptr, i32 } %7, 1 + store i32 %9, ptr %3, align 4 + br label %10 + +10: + %11 = load i32, ptr %3, align 4 + %12 = call i32 @llvm.eh.typeid.for(ptr @_ZTIi) + %13 = icmp eq i32 %11, %12 + br i1 %13, label %14, label %20 + +14: + %15 = load ptr, ptr %2, align 8 + %16 = call ptr @__cxa_begin_catch(ptr %15) + %17 = load i32, ptr %16, align 4 + store i32 %17, ptr %4, align 4 + store i32 0, ptr %1, align 4 + call void @__cxa_end_catch() + br label %18 + +18: + %19 = load i32, ptr %1, align 4 + ret i32 %19 + +20: + %21 = load ptr, ptr %2, align 8 + %22 = load i32, ptr %3, align 4 + %23 = insertvalue { ptr, i32 } undef, ptr %21, 0 + %24 = insertvalue { ptr, i32 } %23, i32 %22, 1 + resume { ptr, i32 } %24 + +25: + unreachable +} + +declare i32 @printf(ptr noundef, ...) + +declare ptr @__cxa_allocate_exception(i64) + +declare void @__cxa_throw(ptr, ptr, ptr) + +declare i32 @__gxx_personality_v0(...) + +; Function Attrs: nounwind readnone +declare i32 @llvm.eh.typeid.for(ptr) + +declare ptr @__cxa_begin_catch(ptr) + +declare void @__cxa_end_catch() \ No newline at end of file diff --git a/languages/llvmir/src/test/resources/de/jplag/llvmir/NewExceptionHandling.ll b/languages/llvmir/src/test/resources/de/jplag/llvmir/NewExceptionHandling.ll new file mode 100644 index 000000000..85f0f02e8 --- /dev/null +++ b/languages/llvmir/src/test/resources/de/jplag/llvmir/NewExceptionHandling.ll @@ -0,0 +1,41 @@ +define i32 @f() nounwind personality i32 (...)* @__CxxFrameHandler3 { +entry: + %obj = alloca %struct.Cleanup, align 4 + %e = alloca i32, align 4 + %call = invoke %struct.Cleanup* @"??0Cleanup@@QEAA@XZ"(%struct.Cleanup* nonnull %obj) + to label %invoke.cont unwind label %lpad.catch + +invoke.cont: ; preds = %entry + invoke void @"?may_throw@@YAXXZ"() + to label %invoke.cont.2 unwind label %lpad.cleanup + +invoke.cont.2: ; preds = %invoke.cont + call void @"??_DCleanup@@QEAA@XZ"(%struct.Cleanup* nonnull %obj) nounwind + br label %return + +return: ; preds = %invoke.cont.3, %invoke.cont.2 + %retval.0 = phi i32 [ 0, %invoke.cont.2 ], [ %3, %invoke.cont.3 ] + ret i32 %retval.0 + +lpad.cleanup: ; preds = %invoke.cont.2 + %0 = cleanuppad within none [] + call void @"??1Cleanup@@QEAA@XZ"(%struct.Cleanup* nonnull %obj) nounwind + cleanupret from %0 unwind label %lpad.catch + +lpad.catch: ; preds = %lpad.cleanup, %entry + %1 = catchswitch within none [label %catch.body] unwind label %lpad.terminate + +catch.body: ; preds = %lpad.catch + %catch = catchpad within %1 [%rtti.TypeDescriptor2* @"??_R0H@8", i32 0, i32* %e] + invoke void @"?may_throw@@YAXXZ"() + to label %invoke.cont.3 unwind label %lpad.terminate + +invoke.cont.3: ; preds = %catch.body + %2 = load i32, i32* %e, align 4 + catchret from %catch to label %return + +lpad.terminate: ; preds = %catch.body, %lpad.catch + cleanuppad within none [] + call void @"?terminate@@YAXXZ"() + unreachable +} \ No newline at end of file diff --git a/languages/pom.xml b/languages/pom.xml index 48acb72c6..203275f10 100644 --- a/languages/pom.xml +++ b/languages/pom.xml @@ -14,6 +14,7 @@ csharp emf-metamodel emf-metamodel-dynamic + emf-model golang java kotlin @@ -22,8 +23,11 @@ rust scala scheme + scxml swift text + typescript + llvmir diff --git a/languages/python-3/README.md b/languages/python-3/README.md new file mode 100644 index 000000000..53f3220a4 --- /dev/null +++ b/languages/python-3/README.md @@ -0,0 +1,5 @@ +## Python language module + +Extracts tokens from python source files using ANTLR. The grammar is taken from the official (antlr repository)[https://github.com/antlr/grammars-v4/tree/master/python/python3] + +The grammar is built for python 3.6. \ No newline at end of file diff --git a/languages/python-3/src/main/antlr4/de/jplag/python3/grammar/Python3.g4 b/languages/python-3/src/main/antlr4/de/jplag/python3/grammar/Python3.g4 deleted file mode 100644 index 44c374831..000000000 --- a/languages/python-3/src/main/antlr4/de/jplag/python3/grammar/Python3.g4 +++ /dev/null @@ -1,1151 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2014 by Bart Kiers - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Project : python3-parser; an ANTLR4 grammar for Python 3 - * https://github.com/bkiers/python3-parser - * Developed by : Bart Kiers, bart@big-o.nl - */ -grammar Python3; - -// All comments that start with "///" are copy-pasted from -// The Python Language Reference: https://docs.python.org/3.3/reference/grammar.html - -tokens { INDENT, DEDENT } - -@lexer::members { - // A queue where extra tokens are pushed on (see the NEWLINE lexer rule). - private java.util.LinkedList tokens = new java.util.LinkedList<>(); - // The stack that keeps track of the indentation level. - private java.util.Stack indents = new java.util.Stack<>(); - // The amount of opened braces, brackets and parenthesis. - private int opened = 0; - // The most recently produced token. - private Token lastToken = null; - @Override - public void emit(Token t) { - super.setToken(t); - tokens.offer(t); - } - - @Override - public Token nextToken() { - // Check if the end-of-file is ahead and there are still some DEDENTS expected. - if (_input.LA(1) == EOF && !this.indents.isEmpty()) { - // Remove any trailing EOF tokens from our buffer. - for (int i = tokens.size() - 1; i >= 0; i--) { - if (tokens.get(i).getType() == EOF) { - tokens.remove(i); - } - } - - // First emit an extra line break that serves as the end of the statement. - this.emit(commonToken(Python3Parser.NEWLINE, "\n")); - - // Now emit as much DEDENT tokens as needed. - while (!indents.isEmpty()) { - this.emit(createDedent()); - indents.pop(); - } - - // Put the EOF back on the token stream. - this.emit(commonToken(Python3Parser.EOF, "")); - } - - Token next = super.nextToken(); - - if (next.getChannel() == Token.DEFAULT_CHANNEL) { - // Keep track of the last token on the default channel. - this.lastToken = next; - } - - return tokens.isEmpty() ? next : tokens.poll(); - } - - private Token createDedent() { - CommonToken dedent = commonToken(Python3Parser.DEDENT, ""); - dedent.setLine(this.lastToken.getLine()); - return dedent; - } - - private CommonToken commonToken(int type, String text) { - int stop = this.getCharIndex() - 1; - int start = text.isEmpty() ? stop : stop - text.length() + 1; - return new CommonToken(this._tokenFactorySourcePair, type, DEFAULT_TOKEN_CHANNEL, start, stop); - } - - // Calculates the indentation of the provided spaces, taking the - // following rules into account: - // - // "Tabs are replaced (from left to right) by one to eight spaces - // such that the total number of characters up to and including - // the replacement is a multiple of eight [...]" - // - // -- https://docs.python.org/3.1/reference/lexical_analysis.html#indentation - static int getIndentationCount(String spaces) { - int count = 0; - for (char ch : spaces.toCharArray()) { - switch (ch) { - case '\t': - count += 8 - (count % 8); - break; - default: - // A normal space char. - count++; - } - } - - return count; - } - - boolean atStartOfInput() { - return super.getCharPositionInLine() == 0 && super.getLine() == 1; - } -} - -/* - * parser rules - */ - -single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE; -file_input: (NEWLINE | stmt)* EOF; -eval_input: testlist NEWLINE* EOF; - -decorator: '@' dotted_name ( '(' (arglist)? ')' )? NEWLINE; -decorators: decorator+; -decorated: decorators (classdef | funcdef | async_funcdef); - -async_funcdef: ASYNC funcdef; -funcdef: 'def' NAME parameters ('->' test)? ':' suite; - -parameters: '(' (typedargslist)? ')'; -typedargslist: (tfpdef ('=' test)? (',' tfpdef ('=' test)?)* (',' ( - '*' (tfpdef)? (',' tfpdef ('=' test)?)* (',' ('**' tfpdef (',')?)?)? - | '**' tfpdef (',')?)?)? - | '*' (tfpdef)? (',' tfpdef ('=' test)?)* (',' ('**' tfpdef (',')?)?)? - | '**' tfpdef (',')?); -tfpdef: NAME (':' test)?; -varargslist: (vfpdef ('=' test)? (',' vfpdef ('=' test)?)* (',' ( - '*' (vfpdef)? (',' vfpdef ('=' test)?)* (',' ('**' vfpdef (',')?)?)? - | '**' vfpdef (',')?)?)? - | '*' (vfpdef)? (',' vfpdef ('=' test)?)* (',' ('**' vfpdef (',')?)?)? - | '**' vfpdef (',')? -); -vfpdef: NAME; - -stmt: simple_stmt | compound_stmt; -simple_stmt: small_stmt (';' small_stmt)* (';')? NEWLINE; -small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt | - import_stmt | global_stmt | nonlocal_stmt | assert_stmt); -expr_stmt: testlist_star_expr (annassign | augassign (yield_expr|testlist) | - ('=' (yield_expr|testlist_star_expr))*); -annassign: ':' test ('=' test)?; -testlist_star_expr: (test|star_expr) (',' (test|star_expr))* (',')?; -augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' | - '<<=' | '>>=' | '**=' | '//='); -// For normal and annotated assignments, additional restrictions enforced by the interpreter -del_stmt: 'del' exprlist; -pass_stmt: 'pass'; -flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt; -break_stmt: 'break'; -continue_stmt: 'continue'; -return_stmt: 'return' (testlist)?; -yield_stmt: yield_expr; -raise_stmt: 'raise' (test ('from' test)?)?; -import_stmt: import_name | import_from; -import_name: 'import' dotted_as_names; -// note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS -import_from: ('from' (('.' | '...')* dotted_name | ('.' | '...')+) - 'import' ('*' | '(' import_as_names ')' | import_as_names)); -import_as_name: NAME ('as' NAME)?; -dotted_as_name: dotted_name ('as' NAME)?; -import_as_names: import_as_name (',' import_as_name)* (',')?; -dotted_as_names: dotted_as_name (',' dotted_as_name)*; -dotted_name: NAME ('.' NAME)*; -global_stmt: 'global' NAME (',' NAME)*; -nonlocal_stmt: 'nonlocal' NAME (',' NAME)*; -assert_stmt: 'assert' test (',' test)?; - -compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated | async_stmt; -async_stmt: ASYNC (funcdef | with_stmt | for_stmt); -if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ('else' ':' suite)?; -while_stmt: 'while' test ':' suite ('else' ':' suite)?; -for_stmt: 'for' exprlist 'in' testlist ':' suite ('else' ':' suite)?; -try_stmt: ('try' ':' suite - ((except_clause ':' suite)+ - ('else' ':' suite)? - ('finally' ':' suite)? | - 'finally' ':' suite)); -with_stmt: 'with' with_item (',' with_item)* ':' suite; -with_item: test ('as' expr)?; -// NB compile.c makes sure that the default except clause is last -except_clause: 'except' (test ('as' NAME)?)?; -suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT; - -test: or_test ('if' or_test 'else' test)? | lambdef; -test_nocond: or_test | lambdef_nocond; -lambdef: 'lambda' (varargslist)? ':' test; -lambdef_nocond: 'lambda' (varargslist)? ':' test_nocond; -or_test: and_test ('or' and_test)*; -and_test: not_test ('and' not_test)*; -not_test: 'not' not_test | comparison; -comparison: expr (comp_op expr)*; -// <> isn't actually a valid comparison operator in Python. It's here for the -// sake of a __future__ import described in PEP 401 (which really works :-) -comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'; -star_expr: '*' expr; -expr: xor_expr ('|' xor_expr)*; -xor_expr: and_expr ('^' and_expr)*; -and_expr: shift_expr ('&' shift_expr)*; -shift_expr: arith_expr (('<<'|'>>') arith_expr)*; -arith_expr: term (('+'|'-') term)*; -term: factor (('*'|'@'|'/'|'%'|'//') factor)*; -factor: ('+'|'-'|'~') factor | power; -power: atom_expr ('**' factor)?; -atom_expr: (AWAIT)? atom trailer*; -atom: ('(' (yield_expr|testlist_comp)? ')' | - '[' (testlist_comp)? ']' | - '{' (dictorsetmaker)? '}' | - NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False'); -testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* (',')? ); -trailer: '(' (arglist)? ')' | '[' subscriptlist ']' | '.' NAME; -subscriptlist: subscript (',' subscript)* (',')?; -subscript: test | (test)? ':' (test)? (sliceop)?; -sliceop: ':' (test)?; -exprlist: (expr|star_expr) (',' (expr|star_expr))* (',')?; -testlist: test (',' test)* (',')?; -dictorsetmaker: ( ((test ':' test | '**' expr) - (comp_for | (',' (test ':' test | '**' expr))* (',')?)) | - ((test | star_expr) - (comp_for | (',' (test | star_expr))* (',')?)) ); - -classdef: 'class' NAME ('(' (arglist)? ')')? ':' suite; - -arglist: argument (',' argument)* (',')?; - -// The reason that keywords are test nodes instead of NAME is that using NAME -// results in an ambiguity. ast.c makes sure it's a NAME. -// "test '=' test" is really "keyword '=' test", but we have no such token. -// These need to be in a single rule to avoid grammar that is ambiguous -// to our LL(1) parser. Even though 'test' includes '*expr' in star_expr, -// we explicitly match '*' here, too, to give it proper precedence. -// Illegal combinations and orderings are blocked in ast.c: -// multiple (test comp_for) arguments are blocked; keyword unpackings -// that precede iterable unpackings are blocked; etc. -argument: ( test (comp_for)? | - test '=' test | - '**' test | - '*' test ); - -comp_iter: comp_for | comp_if; -comp_for: (ASYNC)? 'for' exprlist 'in' or_test (comp_iter)?; -comp_if: 'if' test_nocond (comp_iter)?; - -// not used in grammar, but may appear in "node" passed from Parser to Compiler -encoding_decl: NAME; - -yield_expr: 'yield' (yield_arg)?; -yield_arg: 'from' test | testlist; - -/* - * lexer rules - */ - -STRING - : STRING_LITERAL - | BYTES_LITERAL - ; - -NUMBER - : INTEGER - | FLOAT_NUMBER - | IMAG_NUMBER - ; - -INTEGER - : DECIMAL_INTEGER - | OCT_INTEGER - | HEX_INTEGER - | BIN_INTEGER - ; - -DEF : 'def'; -RETURN : 'return'; -RAISE : 'raise'; -FROM : 'from'; -IMPORT : 'import'; -AS : 'as'; -GLOBAL : 'global'; -NONLOCAL : 'nonlocal'; -ASSERT : 'assert'; -IF : 'if'; -ELIF : 'elif'; -ELSE : 'else'; -WHILE : 'while'; -FOR : 'for'; -IN : 'in'; -TRY : 'try'; -FINALLY : 'finally'; -WITH : 'with'; -EXCEPT : 'except'; -LAMBDA : 'lambda'; -OR : 'or'; -AND : 'and'; -NOT : 'not'; -IS : 'is'; -NONE : 'None'; -TRUE : 'True'; -FALSE : 'False'; -CLASS : 'class'; -YIELD : 'yield'; -DEL : 'del'; -PASS : 'pass'; -CONTINUE : 'continue'; -BREAK : 'break'; -ASYNC : 'async'; -AWAIT : 'await'; - -NEWLINE - : ( {atStartOfInput()}? SPACES - | ( '\r'? '\n' | '\r' ) SPACES? - ) - { - String newLine = getText().replaceAll("[^\r\n]+", ""); - String spaces = getText().replaceAll("[\r\n]+", ""); - int next = _input.LA(1); - if (opened > 0 || next == '\r' || next == '\n' || next == '#') { - // If we're inside a list or on a blank line, ignore all indents, - // dedents and line breaks. - skip(); - } - else { - emit(commonToken(NEWLINE, newLine)); - int indent = getIndentationCount(spaces); - int previous = indents.isEmpty() ? 0 : indents.peek(); - if (indent == previous) { - // skip indents of the same size as the present indent-size - skip(); - } - else if (indent > previous) { - indents.push(indent); - emit(commonToken(Python3Parser.INDENT, spaces)); - } - else { - // Possibly emit more than 1 DEDENT token. - while(!indents.isEmpty() && indents.peek() > indent) { - this.emit(createDedent()); - indents.pop(); - } - } - } - } - ; - -/// identifier ::= id_start id_continue* -NAME - : ID_START ID_CONTINUE* - ; - -/// stringliteral ::= [stringprefix](shortstring | longstring) -/// stringprefix ::= "r" | "u" | "R" | "U" | "f" | "F" -/// | "fr" | "Fr" | "fR" | "FR" | "rf" | "rF" | "Rf" | "RF" -STRING_LITERAL - : ( [rR] | [uU] | [fF] | ( [fF] [rR] ) | ( [rR] [fF] ) )? ( SHORT_STRING | LONG_STRING ) - ; - -/// bytesliteral ::= bytesprefix(shortbytes | longbytes) -/// bytesprefix ::= "b" | "B" | "br" | "Br" | "bR" | "BR" | "rb" | "rB" | "Rb" | "RB" -BYTES_LITERAL - : ( [bB] | ( [bB] [rR] ) | ( [rR] [bB] ) ) ( SHORT_BYTES | LONG_BYTES ) - ; - -/// decimalinteger ::= nonzerodigit digit* | "0"+ -DECIMAL_INTEGER - : NON_ZERO_DIGIT DIGIT* - | '0'+ - ; - -/// octinteger ::= "0" ("o" | "O") octdigit+ -OCT_INTEGER - : '0' [oO] OCT_DIGIT+ - ; - -/// hexinteger ::= "0" ("x" | "X") hexdigit+ -HEX_INTEGER - : '0' [xX] HEX_DIGIT+ - ; - -/// bininteger ::= "0" ("b" | "B") bindigit+ -BIN_INTEGER - : '0' [bB] BIN_DIGIT+ - ; - -/// floatnumber ::= pointfloat | exponentfloat -FLOAT_NUMBER - : POINT_FLOAT - | EXPONENT_FLOAT - ; - -/// imagnumber ::= (floatnumber | intpart) ("j" | "J") -IMAG_NUMBER - : ( FLOAT_NUMBER | INT_PART ) [jJ] - ; - -DOT : '.'; -ELLIPSIS : '...'; -STAR : '*'; -OPEN_PAREN : '(' {opened++;}; -CLOSE_PAREN : ')' {opened--;}; -COMMA : ','; -COLON : ':'; -SEMI_COLON : ';'; -POWER : '**'; -ASSIGN : '='; -OPEN_BRACK : '[' {opened++;}; -CLOSE_BRACK : ']' {opened--;}; -OR_OP : '|'; -XOR : '^'; -AND_OP : '&'; -LEFT_SHIFT : '<<'; -RIGHT_SHIFT : '>>'; -ADD : '+'; -MINUS : '-'; -DIV : '/'; -MOD : '%'; -IDIV : '//'; -NOT_OP : '~'; -OPEN_BRACE : '{' {opened++;}; -CLOSE_BRACE : '}' {opened--;}; -LESS_THAN : '<'; -GREATER_THAN : '>'; -EQUALS : '=='; -GT_EQ : '>='; -LT_EQ : '<='; -NOT_EQ_1 : '<>'; -NOT_EQ_2 : '!='; -AT : '@'; -ARROW : '->'; -ADD_ASSIGN : '+='; -SUB_ASSIGN : '-='; -MULT_ASSIGN : '*='; -AT_ASSIGN : '@='; -DIV_ASSIGN : '/='; -MOD_ASSIGN : '%='; -AND_ASSIGN : '&='; -OR_ASSIGN : '|='; -XOR_ASSIGN : '^='; -LEFT_SHIFT_ASSIGN : '<<='; -RIGHT_SHIFT_ASSIGN : '>>='; -POWER_ASSIGN : '**='; -IDIV_ASSIGN : '//='; - -SKIP_ - : ( SPACES | COMMENT | LINE_JOINING ) -> skip - ; - -UNKNOWN_CHAR - : . - ; - -/* - * fragments - */ - -/// shortstring ::= "'" shortstringitem* "'" | '"' shortstringitem* '"' -/// shortstringitem ::= shortstringchar | stringescapeseq -/// shortstringchar ::= -fragment SHORT_STRING - : '\'' ( STRING_ESCAPE_SEQ | ~[\\\r\n'] )* '\'' - | '"' ( STRING_ESCAPE_SEQ | ~[\\\r\n"] )* '"' - ; -/// longstring ::= "'''" longstringitem* "'''" | '"""' longstringitem* '"""' -fragment LONG_STRING - : '\'\'\'' LONG_STRING_ITEM*? '\'\'\'' - | '"""' LONG_STRING_ITEM*? '"""' - ; - -/// longstringitem ::= longstringchar | stringescapeseq -fragment LONG_STRING_ITEM - : LONG_STRING_CHAR - | STRING_ESCAPE_SEQ - ; - -/// longstringchar ::= -fragment LONG_STRING_CHAR - : ~'\\' - ; - -/// stringescapeseq ::= "\" -fragment STRING_ESCAPE_SEQ - : '\\' . - | '\\' NEWLINE - ; - -/// nonzerodigit ::= "1"..."9" -fragment NON_ZERO_DIGIT - : [1-9] - ; - -/// digit ::= "0"..."9" -fragment DIGIT - : [0-9] - ; - -/// octdigit ::= "0"..."7" -fragment OCT_DIGIT - : [0-7] - ; - -/// hexdigit ::= digit | "a"..."f" | "A"..."F" -fragment HEX_DIGIT - : [0-9a-fA-F] - ; - -/// bindigit ::= "0" | "1" -fragment BIN_DIGIT - : [01] - ; - -/// pointfloat ::= [intpart] fraction | intpart "." -fragment POINT_FLOAT - : INT_PART? FRACTION - | INT_PART '.' - ; - -/// exponentfloat ::= (intpart | pointfloat) exponent -fragment EXPONENT_FLOAT - : ( INT_PART | POINT_FLOAT ) EXPONENT - ; - -/// intpart ::= digit+ -fragment INT_PART - : DIGIT+ - ; - -/// fraction ::= "." digit+ -fragment FRACTION - : '.' DIGIT+ - ; - -/// exponent ::= ("e" | "E") ["+" | "-"] digit+ -fragment EXPONENT - : [eE] [+-]? DIGIT+ - ; - -/// shortbytes ::= "'" shortbytesitem* "'" | '"' shortbytesitem* '"' -/// shortbytesitem ::= shortbyteschar | bytesescapeseq -fragment SHORT_BYTES - : '\'' ( SHORT_BYTES_CHAR_NO_SINGLE_QUOTE | BYTES_ESCAPE_SEQ )* '\'' - | '"' ( SHORT_BYTES_CHAR_NO_DOUBLE_QUOTE | BYTES_ESCAPE_SEQ )* '"' - ; - -/// longbytes ::= "'''" longbytesitem* "'''" | '"""' longbytesitem* '"""' -fragment LONG_BYTES - : '\'\'\'' LONG_BYTES_ITEM*? '\'\'\'' - | '"""' LONG_BYTES_ITEM*? '"""' - ; - -/// longbytesitem ::= longbyteschar | bytesescapeseq -fragment LONG_BYTES_ITEM - : LONG_BYTES_CHAR - | BYTES_ESCAPE_SEQ - ; - -/// shortbyteschar ::= -fragment SHORT_BYTES_CHAR_NO_SINGLE_QUOTE - : [\u0000-\u0009] - | [\u000B-\u000C] - | [\u000E-\u0026] - | [\u0028-\u005B] - | [\u005D-\u007F] - ; - -fragment SHORT_BYTES_CHAR_NO_DOUBLE_QUOTE - : [\u0000-\u0009] - | [\u000B-\u000C] - | [\u000E-\u0021] - | [\u0023-\u005B] - | [\u005D-\u007F] - ; - -/// longbyteschar ::= -fragment LONG_BYTES_CHAR - : [\u0000-\u005B] - | [\u005D-\u007F] - ; - -/// bytesescapeseq ::= "\" -fragment BYTES_ESCAPE_SEQ - : '\\' [\u0000-\u007F] - ; - -fragment SPACES - : [ \t]+ - ; - -fragment COMMENT - : '#' ~[\r\n]* - ; - -fragment LINE_JOINING - : '\\' SPACES? ( '\r'? '\n' | '\r' ) - ; - -/// id_start ::= -fragment ID_START - : '_' - | [A-Z] - | [a-z] - | '\u00AA' - | '\u00B5' - | '\u00BA' - | [\u00C0-\u00D6] - | [\u00D8-\u00F6] - | [\u00F8-\u01BA] - | '\u01BB' - | [\u01BC-\u01BF] - | [\u01C0-\u01C3] - | [\u01C4-\u0241] - | [\u0250-\u02AF] - | [\u02B0-\u02C1] - | [\u02C6-\u02D1] - | [\u02E0-\u02E4] - | '\u02EE' - | '\u037A' - | '\u0386' - | [\u0388-\u038A] - | '\u038C' - | [\u038E-\u03A1] - | [\u03A3-\u03CE] - | [\u03D0-\u03F5] - | [\u03F7-\u0481] - | [\u048A-\u04CE] - | [\u04D0-\u04F9] - | [\u0500-\u050F] - | [\u0531-\u0556] - | '\u0559' - | [\u0561-\u0587] - | [\u05D0-\u05EA] - | [\u05F0-\u05F2] - | [\u0621-\u063A] - | '\u0640' - | [\u0641-\u064A] - | [\u066E-\u066F] - | [\u0671-\u06D3] - | '\u06D5' - | [\u06E5-\u06E6] - | [\u06EE-\u06EF] - | [\u06FA-\u06FC] - | '\u06FF' - | '\u0710' - | [\u0712-\u072F] - | [\u074D-\u076D] - | [\u0780-\u07A5] - | '\u07B1' - | [\u0904-\u0939] - | '\u093D' - | '\u0950' - | [\u0958-\u0961] - | '\u097D' - | [\u0985-\u098C] - | [\u098F-\u0990] - | [\u0993-\u09A8] - | [\u09AA-\u09B0] - | '\u09B2' - | [\u09B6-\u09B9] - | '\u09BD' - | '\u09CE' - | [\u09DC-\u09DD] - | [\u09DF-\u09E1] - | [\u09F0-\u09F1] - | [\u0A05-\u0A0A] - | [\u0A0F-\u0A10] - | [\u0A13-\u0A28] - | [\u0A2A-\u0A30] - | [\u0A32-\u0A33] - | [\u0A35-\u0A36] - | [\u0A38-\u0A39] - | [\u0A59-\u0A5C] - | '\u0A5E' - | [\u0A72-\u0A74] - | [\u0A85-\u0A8D] - | [\u0A8F-\u0A91] - | [\u0A93-\u0AA8] - | [\u0AAA-\u0AB0] - | [\u0AB2-\u0AB3] - | [\u0AB5-\u0AB9] - | '\u0ABD' - | '\u0AD0' - | [\u0AE0-\u0AE1] - | [\u0B05-\u0B0C] - | [\u0B0F-\u0B10] - | [\u0B13-\u0B28] - | [\u0B2A-\u0B30] - | [\u0B32-\u0B33] - | [\u0B35-\u0B39] - | '\u0B3D' - | [\u0B5C-\u0B5D] - | [\u0B5F-\u0B61] - | '\u0B71' - | '\u0B83' - | [\u0B85-\u0B8A] - | [\u0B8E-\u0B90] - | [\u0B92-\u0B95] - | [\u0B99-\u0B9A] - | '\u0B9C' - | [\u0B9E-\u0B9F] - | [\u0BA3-\u0BA4] - | [\u0BA8-\u0BAA] - | [\u0BAE-\u0BB9] - | [\u0C05-\u0C0C] - | [\u0C0E-\u0C10] - | [\u0C12-\u0C28] - | [\u0C2A-\u0C33] - | [\u0C35-\u0C39] - | [\u0C60-\u0C61] - | [\u0C85-\u0C8C] - | [\u0C8E-\u0C90] - | [\u0C92-\u0CA8] - | [\u0CAA-\u0CB3] - | [\u0CB5-\u0CB9] - | '\u0CBD' - | '\u0CDE' - | [\u0CE0-\u0CE1] - | [\u0D05-\u0D0C] - | [\u0D0E-\u0D10] - | [\u0D12-\u0D28] - | [\u0D2A-\u0D39] - | [\u0D60-\u0D61] - | [\u0D85-\u0D96] - | [\u0D9A-\u0DB1] - | [\u0DB3-\u0DBB] - | '\u0DBD' - | [\u0DC0-\u0DC6] - | [\u0E01-\u0E30] - | [\u0E32-\u0E33] - | [\u0E40-\u0E45] - | '\u0E46' - | [\u0E81-\u0E82] - | '\u0E84' - | [\u0E87-\u0E88] - | '\u0E8A' - | '\u0E8D' - | [\u0E94-\u0E97] - | [\u0E99-\u0E9F] - | [\u0EA1-\u0EA3] - | '\u0EA5' - | '\u0EA7' - | [\u0EAA-\u0EAB] - | [\u0EAD-\u0EB0] - | [\u0EB2-\u0EB3] - | '\u0EBD' - | [\u0EC0-\u0EC4] - | '\u0EC6' - | [\u0EDC-\u0EDD] - | '\u0F00' - | [\u0F40-\u0F47] - | [\u0F49-\u0F6A] - | [\u0F88-\u0F8B] - | [\u1000-\u1021] - | [\u1023-\u1027] - | [\u1029-\u102A] - | [\u1050-\u1055] - | [\u10A0-\u10C5] - | [\u10D0-\u10FA] - | '\u10FC' - | [\u1100-\u1159] - | [\u115F-\u11A2] - | [\u11A8-\u11F9] - | [\u1200-\u1248] - | [\u124A-\u124D] - | [\u1250-\u1256] - | '\u1258' - | [\u125A-\u125D] - | [\u1260-\u1288] - | [\u128A-\u128D] - | [\u1290-\u12B0] - | [\u12B2-\u12B5] - | [\u12B8-\u12BE] - | '\u12C0' - | [\u12C2-\u12C5] - | [\u12C8-\u12D6] - | [\u12D8-\u1310] - | [\u1312-\u1315] - | [\u1318-\u135A] - | [\u1380-\u138F] - | [\u13A0-\u13F4] - | [\u1401-\u166C] - | [\u166F-\u1676] - | [\u1681-\u169A] - | [\u16A0-\u16EA] - | [\u16EE-\u16F0] - | [\u1700-\u170C] - | [\u170E-\u1711] - | [\u1720-\u1731] - | [\u1740-\u1751] - | [\u1760-\u176C] - | [\u176E-\u1770] - | [\u1780-\u17B3] - | '\u17D7' - | '\u17DC' - | [\u1820-\u1842] - | '\u1843' - | [\u1844-\u1877] - | [\u1880-\u18A8] - | [\u1900-\u191C] - | [\u1950-\u196D] - | [\u1970-\u1974] - | [\u1980-\u19A9] - | [\u19C1-\u19C7] - | [\u1A00-\u1A16] - | [\u1D00-\u1D2B] - | [\u1D2C-\u1D61] - | [\u1D62-\u1D77] - | '\u1D78' - | [\u1D79-\u1D9A] - | [\u1D9B-\u1DBF] - | [\u1E00-\u1E9B] - | [\u1EA0-\u1EF9] - | [\u1F00-\u1F15] - | [\u1F18-\u1F1D] - | [\u1F20-\u1F45] - | [\u1F48-\u1F4D] - | [\u1F50-\u1F57] - | '\u1F59' - | '\u1F5B' - | '\u1F5D' - | [\u1F5F-\u1F7D] - | [\u1F80-\u1FB4] - | [\u1FB6-\u1FBC] - | '\u1FBE' - | [\u1FC2-\u1FC4] - | [\u1FC6-\u1FCC] - | [\u1FD0-\u1FD3] - | [\u1FD6-\u1FDB] - | [\u1FE0-\u1FEC] - | [\u1FF2-\u1FF4] - | [\u1FF6-\u1FFC] - | '\u2071' - | '\u207F' - | [\u2090-\u2094] - | '\u2102' - | '\u2107' - | [\u210A-\u2113] - | '\u2115' - | '\u2118' - | [\u2119-\u211D] - | '\u2124' - | '\u2126' - | '\u2128' - | [\u212A-\u212D] - | '\u212E' - | [\u212F-\u2131] - | [\u2133-\u2134] - | [\u2135-\u2138] - | '\u2139' - | [\u213C-\u213F] - | [\u2145-\u2149] - | [\u2160-\u2183] - | [\u2C00-\u2C2E] - | [\u2C30-\u2C5E] - | [\u2C80-\u2CE4] - | [\u2D00-\u2D25] - | [\u2D30-\u2D65] - | '\u2D6F' - | [\u2D80-\u2D96] - | [\u2DA0-\u2DA6] - | [\u2DA8-\u2DAE] - | [\u2DB0-\u2DB6] - | [\u2DB8-\u2DBE] - | [\u2DC0-\u2DC6] - | [\u2DC8-\u2DCE] - | [\u2DD0-\u2DD6] - | [\u2DD8-\u2DDE] - | '\u3005' - | '\u3006' - | '\u3007' - | [\u3021-\u3029] - | [\u3031-\u3035] - | [\u3038-\u303A] - | '\u303B' - | '\u303C' - | [\u3041-\u3096] - | [\u309B-\u309C] - | [\u309D-\u309E] - | '\u309F' - | [\u30A1-\u30FA] - | [\u30FC-\u30FE] - | '\u30FF' - | [\u3105-\u312C] - | [\u3131-\u318E] - | [\u31A0-\u31B7] - | [\u31F0-\u31FF] - | [\u3400-\u4DB5] - | [\u4E00-\u9FBB] - | [\uA000-\uA014] - | '\uA015' - | [\uA016-\uA48C] - | [\uA800-\uA801] - | [\uA803-\uA805] - | [\uA807-\uA80A] - | [\uA80C-\uA822] - | [\uAC00-\uD7A3] - | [\uF900-\uFA2D] - | [\uFA30-\uFA6A] - | [\uFA70-\uFAD9] - | [\uFB00-\uFB06] - | [\uFB13-\uFB17] - | '\uFB1D' - | [\uFB1F-\uFB28] - | [\uFB2A-\uFB36] - | [\uFB38-\uFB3C] - | '\uFB3E' - | [\uFB40-\uFB41] - | [\uFB43-\uFB44] - | [\uFB46-\uFBB1] - | [\uFBD3-\uFD3D] - | [\uFD50-\uFD8F] - | [\uFD92-\uFDC7] - | [\uFDF0-\uFDFB] - | [\uFE70-\uFE74] - | [\uFE76-\uFEFC] - | [\uFF21-\uFF3A] - | [\uFF41-\uFF5A] - | [\uFF66-\uFF6F] - | '\uFF70' - | [\uFF71-\uFF9D] - | [\uFF9E-\uFF9F] - | [\uFFA0-\uFFBE] - | [\uFFC2-\uFFC7] - | [\uFFCA-\uFFCF] - | [\uFFD2-\uFFD7] - | [\uFFDA-\uFFDC] - ; - -/// id_continue ::= -fragment ID_CONTINUE - : ID_START - | [0-9] - | [\u0300-\u036F] - | [\u0483-\u0486] - | [\u0591-\u05B9] - | [\u05BB-\u05BD] - | '\u05BF' - | [\u05C1-\u05C2] - | [\u05C4-\u05C5] - | '\u05C7' - | [\u0610-\u0615] - | [\u064B-\u065E] - | [\u0660-\u0669] - | '\u0670' - | [\u06D6-\u06DC] - | [\u06DF-\u06E4] - | [\u06E7-\u06E8] - | [\u06EA-\u06ED] - | [\u06F0-\u06F9] - | '\u0711' - | [\u0730-\u074A] - | [\u07A6-\u07B0] - | [\u0901-\u0902] - | '\u0903' - | '\u093C' - | [\u093E-\u0940] - | [\u0941-\u0948] - | [\u0949-\u094C] - | '\u094D' - | [\u0951-\u0954] - | [\u0962-\u0963] - | [\u0966-\u096F] - | '\u0981' - | [\u0982-\u0983] - | '\u09BC' - | [\u09BE-\u09C0] - | [\u09C1-\u09C4] - | [\u09C7-\u09C8] - | [\u09CB-\u09CC] - | '\u09CD' - | '\u09D7' - | [\u09E2-\u09E3] - | [\u09E6-\u09EF] - | [\u0A01-\u0A02] - | '\u0A03' - | '\u0A3C' - | [\u0A3E-\u0A40] - | [\u0A41-\u0A42] - | [\u0A47-\u0A48] - | [\u0A4B-\u0A4D] - | [\u0A66-\u0A6F] - | [\u0A70-\u0A71] - | [\u0A81-\u0A82] - | '\u0A83' - | '\u0ABC' - | [\u0ABE-\u0AC0] - | [\u0AC1-\u0AC5] - | [\u0AC7-\u0AC8] - | '\u0AC9' - | [\u0ACB-\u0ACC] - | '\u0ACD' - | [\u0AE2-\u0AE3] - | [\u0AE6-\u0AEF] - | '\u0B01' - | [\u0B02-\u0B03] - | '\u0B3C' - | '\u0B3E' - | '\u0B3F' - | '\u0B40' - | [\u0B41-\u0B43] - | [\u0B47-\u0B48] - | [\u0B4B-\u0B4C] - | '\u0B4D' - | '\u0B56' - | '\u0B57' - | [\u0B66-\u0B6F] - | '\u0B82' - | [\u0BBE-\u0BBF] - | '\u0BC0' - | [\u0BC1-\u0BC2] - | [\u0BC6-\u0BC8] - | [\u0BCA-\u0BCC] - | '\u0BCD' - | '\u0BD7' - | [\u0BE6-\u0BEF] - | [\u0C01-\u0C03] - | [\u0C3E-\u0C40] - | [\u0C41-\u0C44] - | [\u0C46-\u0C48] - | [\u0C4A-\u0C4D] - | [\u0C55-\u0C56] - | [\u0C66-\u0C6F] - | [\u0C82-\u0C83] - | '\u0CBC' - | '\u0CBE' - | '\u0CBF' - | [\u0CC0-\u0CC4] - | '\u0CC6' - | [\u0CC7-\u0CC8] - | [\u0CCA-\u0CCB] - | [\u0CCC-\u0CCD] - | [\u0CD5-\u0CD6] - | [\u0CE6-\u0CEF] - | [\u0D02-\u0D03] - | [\u0D3E-\u0D40] - | [\u0D41-\u0D43] - | [\u0D46-\u0D48] - | [\u0D4A-\u0D4C] - | '\u0D4D' - | '\u0D57' - | [\u0D66-\u0D6F] - | [\u0D82-\u0D83] - | '\u0DCA' - | [\u0DCF-\u0DD1] - | [\u0DD2-\u0DD4] - | '\u0DD6' - | [\u0DD8-\u0DDF] - | [\u0DF2-\u0DF3] - | '\u0E31' - | [\u0E34-\u0E3A] - | [\u0E47-\u0E4E] - | [\u0E50-\u0E59] - | '\u0EB1' - | [\u0EB4-\u0EB9] - | [\u0EBB-\u0EBC] - | [\u0EC8-\u0ECD] - | [\u0ED0-\u0ED9] - | [\u0F18-\u0F19] - | [\u0F20-\u0F29] - | '\u0F35' - | '\u0F37' - | '\u0F39' - | [\u0F3E-\u0F3F] - | [\u0F71-\u0F7E] - | '\u0F7F' - | [\u0F80-\u0F84] - | [\u0F86-\u0F87] - | [\u0F90-\u0F97] - | [\u0F99-\u0FBC] - | '\u0FC6' - | '\u102C' - | [\u102D-\u1030] - | '\u1031' - | '\u1032' - | [\u1036-\u1037] - | '\u1038' - | '\u1039' - | [\u1040-\u1049] - | [\u1056-\u1057] - | [\u1058-\u1059] - | '\u135F' - | [\u1369-\u1371] - | [\u1712-\u1714] - | [\u1732-\u1734] - | [\u1752-\u1753] - | [\u1772-\u1773] - | '\u17B6' - | [\u17B7-\u17BD] - | [\u17BE-\u17C5] - | '\u17C6' - | [\u17C7-\u17C8] - | [\u17C9-\u17D3] - | '\u17DD' - | [\u17E0-\u17E9] - | [\u180B-\u180D] - | [\u1810-\u1819] - | '\u18A9' - | [\u1920-\u1922] - | [\u1923-\u1926] - | [\u1927-\u1928] - | [\u1929-\u192B] - | [\u1930-\u1931] - | '\u1932' - | [\u1933-\u1938] - | [\u1939-\u193B] - | [\u1946-\u194F] - | [\u19B0-\u19C0] - | [\u19C8-\u19C9] - | [\u19D0-\u19D9] - | [\u1A17-\u1A18] - | [\u1A19-\u1A1B] - | [\u1DC0-\u1DC3] - | [\u203F-\u2040] - | '\u2054' - | [\u20D0-\u20DC] - | '\u20E1' - | [\u20E5-\u20EB] - | [\u302A-\u302F] - | [\u3099-\u309A] - | '\uA802' - | '\uA806' - | '\uA80B' - | [\uA823-\uA824] - | [\uA825-\uA826] - | '\uA827' - | '\uFB1E' - | [\uFE00-\uFE0F] - | [\uFE20-\uFE23] - | [\uFE33-\uFE34] - | [\uFE4D-\uFE4F] - | [\uFF10-\uFF19] - | '\uFF3F' - ; \ No newline at end of file diff --git a/languages/python-3/src/main/antlr4/de/jplag/python3/grammar/Python3Lexer.g4 b/languages/python-3/src/main/antlr4/de/jplag/python3/grammar/Python3Lexer.g4 new file mode 100644 index 000000000..9b5fee1dc --- /dev/null +++ b/languages/python-3/src/main/antlr4/de/jplag/python3/grammar/Python3Lexer.g4 @@ -0,0 +1,404 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2014 by Bart Kiers + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Project : python3-parser; an ANTLR4 grammar for Python 3 + * https://github.com/bkiers/python3-parser + * Developed by : Bart Kiers, bart@big-o.nl + */ +lexer grammar Python3Lexer; + +// All comments that start with "///" are copy-pasted from +// The Python Language Reference + +tokens { INDENT, DEDENT } + +options { + superClass=Python3LexerBase; +} + +/* + * lexer rules + */ + +STRING + : STRING_LITERAL + | BYTES_LITERAL + ; + +NUMBER + : INTEGER + | FLOAT_NUMBER + | IMAG_NUMBER + ; + +INTEGER + : DECIMAL_INTEGER + | OCT_INTEGER + | HEX_INTEGER + | BIN_INTEGER + ; + +AND : 'and'; +AS : 'as'; +ASSERT : 'assert'; +ASYNC : 'async'; +AWAIT : 'await'; +BREAK : 'break'; +CASE : 'case' ; +CLASS : 'class'; +CONTINUE : 'continue'; +DEF : 'def'; +DEL : 'del'; +ELIF : 'elif'; +ELSE : 'else'; +EXCEPT : 'except'; +FALSE : 'False'; +FINALLY : 'finally'; +FOR : 'for'; +FROM : 'from'; +GLOBAL : 'global'; +IF : 'if'; +IMPORT : 'import'; +IN : 'in'; +IS : 'is'; +LAMBDA : 'lambda'; +MATCH : 'match' ; +NONE : 'None'; +NONLOCAL : 'nonlocal'; +NOT : 'not'; +OR : 'or'; +PASS : 'pass'; +RAISE : 'raise'; +RETURN : 'return'; +TRUE : 'True'; +TRY : 'try'; +UNDERSCORE : '_' ; +WHILE : 'while'; +WITH : 'with'; +YIELD : 'yield'; + +NEWLINE + : ( {this.atStartOfInput()}? SPACES + | ( '\r'? '\n' | '\r' | '\f' ) SPACES? + ) + {this.onNewLine();} + ; + +/// identifier ::= id_start id_continue* +NAME + : ID_START ID_CONTINUE* + ; + +/// stringliteral ::= [stringprefix](shortstring | longstring) +/// stringprefix ::= "r" | "u" | "R" | "U" | "f" | "F" +/// | "fr" | "Fr" | "fR" | "FR" | "rf" | "rF" | "Rf" | "RF" +STRING_LITERAL + : ( [rR] | [uU] | [fF] | ( [fF] [rR] ) | ( [rR] [fF] ) )? ( SHORT_STRING | LONG_STRING ) + ; + +/// bytesliteral ::= bytesprefix(shortbytes | longbytes) +/// bytesprefix ::= "b" | "B" | "br" | "Br" | "bR" | "BR" | "rb" | "rB" | "Rb" | "RB" +BYTES_LITERAL + : ( [bB] | ( [bB] [rR] ) | ( [rR] [bB] ) ) ( SHORT_BYTES | LONG_BYTES ) + ; + +/// decimalinteger ::= nonzerodigit digit* | "0"+ +DECIMAL_INTEGER + : NON_ZERO_DIGIT DIGIT* + | '0'+ + ; + +/// octinteger ::= "0" ("o" | "O") octdigit+ +OCT_INTEGER + : '0' [oO] OCT_DIGIT+ + ; + +/// hexinteger ::= "0" ("x" | "X") hexdigit+ +HEX_INTEGER + : '0' [xX] HEX_DIGIT+ + ; + +/// bininteger ::= "0" ("b" | "B") bindigit+ +BIN_INTEGER + : '0' [bB] BIN_DIGIT+ + ; + +/// floatnumber ::= pointfloat | exponentfloat +FLOAT_NUMBER + : POINT_FLOAT + | EXPONENT_FLOAT + ; + +/// imagnumber ::= (floatnumber | intpart) ("j" | "J") +IMAG_NUMBER + : ( FLOAT_NUMBER | INT_PART ) [jJ] + ; + +DOT : '.'; +ELLIPSIS : '...'; +STAR : '*'; +OPEN_PAREN : '(' {this.openBrace();}; +CLOSE_PAREN : ')' {this.closeBrace();}; +COMMA : ','; +COLON : ':'; +SEMI_COLON : ';'; +POWER : '**'; +ASSIGN : '='; +OPEN_BRACK : '[' {this.openBrace();}; +CLOSE_BRACK : ']' {this.closeBrace();}; +OR_OP : '|'; +XOR : '^'; +AND_OP : '&'; +LEFT_SHIFT : '<<'; +RIGHT_SHIFT : '>>'; +ADD : '+'; +MINUS : '-'; +DIV : '/'; +MOD : '%'; +IDIV : '//'; +NOT_OP : '~'; +OPEN_BRACE : '{' {this.openBrace();}; +CLOSE_BRACE : '}' {this.closeBrace();}; +LESS_THAN : '<'; +GREATER_THAN : '>'; +EQUALS : '=='; +GT_EQ : '>='; +LT_EQ : '<='; +NOT_EQ_1 : '<>'; +NOT_EQ_2 : '!='; +AT : '@'; +ARROW : '->'; +ADD_ASSIGN : '+='; +SUB_ASSIGN : '-='; +MULT_ASSIGN : '*='; +AT_ASSIGN : '@='; +DIV_ASSIGN : '/='; +MOD_ASSIGN : '%='; +AND_ASSIGN : '&='; +OR_ASSIGN : '|='; +XOR_ASSIGN : '^='; +LEFT_SHIFT_ASSIGN : '<<='; +RIGHT_SHIFT_ASSIGN : '>>='; +POWER_ASSIGN : '**='; +IDIV_ASSIGN : '//='; + +SKIP_ + : ( SPACES | COMMENT | LINE_JOINING ) -> skip + ; + +UNKNOWN_CHAR + : . + ; + +/* + * fragments + */ + +/// shortstring ::= "'" shortstringitem* "'" | '"' shortstringitem* '"' +/// shortstringitem ::= shortstringchar | stringescapeseq +/// shortstringchar ::= +fragment SHORT_STRING + : '\'' ( STRING_ESCAPE_SEQ | ~[\\\r\n\f'] )* '\'' + | '"' ( STRING_ESCAPE_SEQ | ~[\\\r\n\f"] )* '"' + ; +/// longstring ::= "'''" longstringitem* "'''" | '"""' longstringitem* '"""' +fragment LONG_STRING + : '\'\'\'' LONG_STRING_ITEM*? '\'\'\'' + | '"""' LONG_STRING_ITEM*? '"""' + ; + +/// longstringitem ::= longstringchar | stringescapeseq +fragment LONG_STRING_ITEM + : LONG_STRING_CHAR + | STRING_ESCAPE_SEQ + ; + +/// longstringchar ::= +fragment LONG_STRING_CHAR + : ~'\\' + ; + +/// stringescapeseq ::= "\" +fragment STRING_ESCAPE_SEQ + : '\\' . + | '\\' NEWLINE + ; + +/// nonzerodigit ::= "1"..."9" +fragment NON_ZERO_DIGIT + : [1-9] + ; + +/// digit ::= "0"..."9" +fragment DIGIT + : [0-9] + ; + +/// octdigit ::= "0"..."7" +fragment OCT_DIGIT + : [0-7] + ; + +/// hexdigit ::= digit | "a"..."f" | "A"..."F" +fragment HEX_DIGIT + : [0-9a-fA-F] + ; + +/// bindigit ::= "0" | "1" +fragment BIN_DIGIT + : [01] + ; + +/// pointfloat ::= [intpart] fraction | intpart "." +fragment POINT_FLOAT + : INT_PART? FRACTION + | INT_PART '.' + ; + +/// exponentfloat ::= (intpart | pointfloat) exponent +fragment EXPONENT_FLOAT + : ( INT_PART | POINT_FLOAT ) EXPONENT + ; + +/// intpart ::= digit+ +fragment INT_PART + : DIGIT+ + ; + +/// fraction ::= "." digit+ +fragment FRACTION + : '.' DIGIT+ + ; + +/// exponent ::= ("e" | "E") ["+" | "-"] digit+ +fragment EXPONENT + : [eE] [+-]? DIGIT+ + ; + +/// shortbytes ::= "'" shortbytesitem* "'" | '"' shortbytesitem* '"' +/// shortbytesitem ::= shortbyteschar | bytesescapeseq +fragment SHORT_BYTES + : '\'' ( SHORT_BYTES_CHAR_NO_SINGLE_QUOTE | BYTES_ESCAPE_SEQ )* '\'' + | '"' ( SHORT_BYTES_CHAR_NO_DOUBLE_QUOTE | BYTES_ESCAPE_SEQ )* '"' + ; + +/// longbytes ::= "'''" longbytesitem* "'''" | '"""' longbytesitem* '"""' +fragment LONG_BYTES + : '\'\'\'' LONG_BYTES_ITEM*? '\'\'\'' + | '"""' LONG_BYTES_ITEM*? '"""' + ; + +/// longbytesitem ::= longbyteschar | bytesescapeseq +fragment LONG_BYTES_ITEM + : LONG_BYTES_CHAR + | BYTES_ESCAPE_SEQ + ; + +/// shortbyteschar ::= +fragment SHORT_BYTES_CHAR_NO_SINGLE_QUOTE + : [\u0000-\u0009] + | [\u000B-\u000C] + | [\u000E-\u0026] + | [\u0028-\u005B] + | [\u005D-\u007F] + ; + +fragment SHORT_BYTES_CHAR_NO_DOUBLE_QUOTE + : [\u0000-\u0009] + | [\u000B-\u000C] + | [\u000E-\u0021] + | [\u0023-\u005B] + | [\u005D-\u007F] + ; + +/// longbyteschar ::= +fragment LONG_BYTES_CHAR + : [\u0000-\u005B] + | [\u005D-\u007F] + ; + +/// bytesescapeseq ::= "\" +fragment BYTES_ESCAPE_SEQ + : '\\' [\u0000-\u007F] + ; + +fragment SPACES + : [ \t]+ + ; + +fragment COMMENT + : '#' ~[\r\n\f]* + ; + +fragment LINE_JOINING + : '\\' SPACES? ( '\r'? '\n' | '\r' | '\f') + ; + + +// TODO: ANTLR seems lack of some Unicode property support... +//$ curl https://www.unicode.org/Public/13.0.0/ucd/PropList.txt | grep Other_ID_ +//1885..1886 ; Other_ID_Start # Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA +//2118 ; Other_ID_Start # Sm SCRIPT CAPITAL P +//212E ; Other_ID_Start # So ESTIMATED SYMBOL +//309B..309C ; Other_ID_Start # Sk [2] KATAKANA-HIRAGANA VOICED SOUND MARK..KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK +//00B7 ; Other_ID_Continue # Po MIDDLE DOT +//0387 ; Other_ID_Continue # Po GREEK ANO TELEIA +//1369..1371 ; Other_ID_Continue # No [9] ETHIOPIC DIGIT ONE..ETHIOPIC DIGIT NINE +//19DA ; Other_ID_Continue # No NEW TAI LUE THAM DIGIT ONE + +fragment UNICODE_OIDS + : '\u1885'..'\u1886' + | '\u2118' + | '\u212e' + | '\u309b'..'\u309c' + ; + +fragment UNICODE_OIDC + : '\u00b7' + | '\u0387' + | '\u1369'..'\u1371' + | '\u19da' + ; + +/// id_start ::= +fragment ID_START + : '_' + | [\p{L}] + | [\p{Nl}] + //| [\p{Other_ID_Start}] + | UNICODE_OIDS + ; + +/// id_continue ::= +fragment ID_CONTINUE + : ID_START + | [\p{Mn}] + | [\p{Mc}] + | [\p{Nd}] + | [\p{Pc}] + //| [\p{Other_ID_Continue}] + | UNICODE_OIDC + ; diff --git a/languages/python-3/src/main/antlr4/de/jplag/python3/grammar/Python3Parser.g4 b/languages/python-3/src/main/antlr4/de/jplag/python3/grammar/Python3Parser.g4 new file mode 100644 index 000000000..8b0143de6 --- /dev/null +++ b/languages/python-3/src/main/antlr4/de/jplag/python3/grammar/Python3Parser.g4 @@ -0,0 +1,239 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2014 by Bart Kiers + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Project : python3-parser; an ANTLR4 grammar for Python 3 + * https://github.com/bkiers/python3-parser + * Developed by : Bart Kiers, bart@big-o.nl + */ + +// Scraping from https://docs.python.org/3/reference/grammar.html + +parser grammar Python3Parser; + +options { + superClass = Python3ParserBase; + tokenVocab=Python3Lexer; +} + +// All comments that start with "///" are copy-pasted from +// The Python Language Reference + +single_input: NEWLINE | simple_stmts | compound_stmt NEWLINE; +file_input: (NEWLINE | stmt)* EOF; +eval_input: testlist NEWLINE* EOF; + +decorator: '@' dotted_name ( '(' arglist? ')' )? NEWLINE; +decorators: decorator+; +decorated: decorators (classdef | funcdef | async_funcdef); + +async_funcdef: ASYNC funcdef; +funcdef: 'def' name parameters ('->' test)? ':' block; + +parameters: '(' typedargslist? ')'; +typedargslist: (tfpdef ('=' test)? (',' tfpdef ('=' test)?)* (',' ( + '*' tfpdef? (',' tfpdef ('=' test)?)* (',' ('**' tfpdef ','? )? )? + | '**' tfpdef ','? )? )? + | '*' tfpdef? (',' tfpdef ('=' test)?)* (',' ('**' tfpdef ','? )? )? + | '**' tfpdef ','?); +tfpdef: name (':' test)?; +varargslist: (vfpdef ('=' test)? (',' vfpdef ('=' test)?)* (',' ( + '*' vfpdef? (',' vfpdef ('=' test)?)* (',' ('**' vfpdef ','? )? )? + | '**' vfpdef (',')?)?)? + | '*' vfpdef? (',' vfpdef ('=' test)?)* (',' ('**' vfpdef ','? )? )? + | '**' vfpdef ','? +); +vfpdef: name; + +stmt: simple_stmts | compound_stmt; +simple_stmts: simple_stmt (';' simple_stmt)* ';'? NEWLINE; +simple_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt | + import_stmt | global_stmt | nonlocal_stmt | assert_stmt); +expr_stmt: testlist_star_expr (annassign | augassign (yield_expr|testlist) | + ('=' (yield_expr|testlist_star_expr))*); +annassign: ':' test ('=' test)?; +testlist_star_expr: (test|star_expr) (',' (test|star_expr))* ','?; +augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' | + '<<=' | '>>=' | '**=' | '//='); +// For normal and annotated assignments, additional restrictions enforced by the interpreter +del_stmt: 'del' exprlist; +pass_stmt: 'pass'; +flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt; +break_stmt: 'break'; +continue_stmt: 'continue'; +return_stmt: 'return' testlist?; +yield_stmt: yield_expr; +raise_stmt: 'raise' (test ('from' test)?)?; +import_stmt: import_name | import_from; +import_name: 'import' dotted_as_names; +// note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS +import_from: ('from' (('.' | '...')* dotted_name | ('.' | '...')+) + 'import' ('*' | '(' import_as_names ')' | import_as_names)); +import_as_name: name ('as' name)?; +dotted_as_name: dotted_name ('as' name)?; +import_as_names: import_as_name (',' import_as_name)* ','?; +dotted_as_names: dotted_as_name (',' dotted_as_name)*; +dotted_name: name ('.' name)*; +global_stmt: 'global' name (',' name)*; +nonlocal_stmt: 'nonlocal' name (',' name)*; +assert_stmt: 'assert' test (',' test)?; + +compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated | async_stmt | match_stmt; +async_stmt: ASYNC (funcdef | with_stmt | for_stmt); +if_stmt: 'if' test ':' block ('elif' test ':' block)* ('else' ':' block)?; +while_stmt: 'while' test ':' block ('else' ':' block)?; +for_stmt: 'for' exprlist 'in' testlist ':' block ('else' ':' block)?; +try_stmt: ('try' ':' block + ((except_clause ':' block)+ + ('else' ':' block)? + ('finally' ':' block)? | + 'finally' ':' block)); +with_stmt: 'with' with_item (',' with_item)* ':' block; +with_item: test ('as' expr)?; +// NB compile.c makes sure that the default except clause is last +except_clause: 'except' (test ('as' name)?)?; +block: simple_stmts | NEWLINE INDENT stmt+ DEDENT; +match_stmt: 'match' subject_expr ':' NEWLINE INDENT case_block+ DEDENT ; +subject_expr: star_named_expression ',' star_named_expressions? | test ; +star_named_expressions: ',' star_named_expression+ ','? ; +star_named_expression: '*' expr | test ; +case_block: 'case' patterns guard? ':' block ; +guard: 'if' test ; +patterns: open_sequence_pattern | pattern ; +pattern: as_pattern | or_pattern ; +as_pattern: or_pattern 'as' pattern_capture_target ; +or_pattern: closed_pattern ('|' closed_pattern)* ; +closed_pattern: literal_pattern | capture_pattern | wildcard_pattern | value_pattern | group_pattern | sequence_pattern | mapping_pattern | class_pattern ; +literal_pattern: signed_number { this.cannotBePlusMinus() }? | complex_number | strings | 'None' | 'True' | 'False' ; +literal_expr: signed_number { this.cannotBePlusMinus() }? | complex_number | strings | 'None' | 'True' | 'False' ; +complex_number: signed_real_number '+' imaginary_number + | signed_real_number '-' imaginary_number + ; +signed_number: NUMBER | '-' NUMBER ; +signed_real_number: real_number | '-' real_number ; +real_number: NUMBER ; +imaginary_number: NUMBER ; +capture_pattern: pattern_capture_target ; +pattern_capture_target: /* cannot be '_' */ name { this.cannotBeDotLpEq() }? ; +wildcard_pattern: '_' ; +value_pattern: attr { this.cannotBeDotLpEq() }? ; +attr: name ('.' name)+ ; +name_or_attr: attr | name ; +group_pattern: '(' pattern ')' ; +sequence_pattern: + '[' maybe_sequence_pattern? ']' + | '(' open_sequence_pattern? ')' + ; +open_sequence_pattern: maybe_star_pattern ',' maybe_sequence_pattern? ; +maybe_sequence_pattern: maybe_star_pattern (',' maybe_star_pattern)* ','? ; +maybe_star_pattern: star_pattern | pattern ; +star_pattern: + '*' pattern_capture_target + | '*' wildcard_pattern + ; +mapping_pattern: '{' '}' + | '{' double_star_pattern ','? '}' + | '{' items_pattern ',' double_star_pattern ','? '}' + | '{' items_pattern ','? '}' + ; +items_pattern: key_value_pattern (',' key_value_pattern)* ; +key_value_pattern: (literal_expr | attr) ':' pattern ; +double_star_pattern: '**' pattern_capture_target ; +class_pattern: name_or_attr '(' ')' + | name_or_attr '(' positional_patterns ','? ')' + | name_or_attr '(' keyword_patterns ','? ')' + | name_or_attr '(' positional_patterns ',' keyword_patterns ','? ')' + ; +positional_patterns: pattern (',' pattern)* ; +keyword_patterns: keyword_pattern (',' keyword_pattern)* ; +keyword_pattern: name '=' pattern ; + +test: or_test ('if' or_test 'else' test)? | lambdef; +test_nocond: or_test | lambdef_nocond; +lambdef: 'lambda' varargslist? ':' test; +lambdef_nocond: 'lambda' varargslist? ':' test_nocond; +or_test: and_test ('or' and_test)*; +and_test: not_test ('and' not_test)*; +not_test: 'not' not_test | comparison; +comparison: expr (comp_op expr)*; +// <> isn't actually a valid comparison operator in Python. It's here for the +// sake of a __future__ import described in PEP 401 (which really works :-) +comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'; +star_expr: '*' expr; +expr: xor_expr ('|' xor_expr)*; +xor_expr: and_expr ('^' and_expr)*; +and_expr: shift_expr ('&' shift_expr)*; +shift_expr: arith_expr (('<<'|'>>') arith_expr)*; +arith_expr: term (('+'|'-') term)*; +term: factor (('*'|'@'|'/'|'%'|'//') factor)*; +factor: ('+'|'-'|'~') factor | power; +power: atom_expr ('**' factor)?; +atom_expr: AWAIT? atom trailer*; +atom: '(' (yield_expr|testlist_comp)? ')' + | '[' testlist_comp? ']' + | '{' dictorsetmaker? '}' + | name | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False' ; +name : NAME | '_' | 'match' ; +testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* ','? ); +trailer: '(' arglist? ')' | '[' subscriptlist ']' | '.' name ; +subscriptlist: subscript_ (',' subscript_)* ','?; +subscript_: test | test? ':' test? sliceop?; +sliceop: ':' test?; +exprlist: (expr|star_expr) (',' (expr|star_expr))* ','?; +testlist: test (',' test)* ','?; +dictorsetmaker: ( ((test ':' test | '**' expr) + (comp_for | (',' (test ':' test | '**' expr))* ','?)) | + ((test | star_expr) + (comp_for | (',' (test | star_expr))* ','?)) ); + +classdef: 'class' name ('(' arglist? ')')? ':' block; + +arglist: argument (',' argument)* ','?; + +// The reason that keywords are test nodes instead of NAME is that using NAME +// results in an ambiguity. ast.c makes sure it's a NAME. +// "test '=' test" is really "keyword '=' test", but we have no such token. +// These need to be in a single rule to avoid grammar that is ambiguous +// to our LL(1) parser. Even though 'test' includes '*expr' in star_expr, +// we explicitly match '*' here, too, to give it proper precedence. +// Illegal combinations and orderings are blocked in ast.c: +// multiple (test comp_for) arguments are blocked; keyword unpackings +// that precede iterable unpackings are blocked; etc. +argument: ( test comp_for? | + test '=' test | + '**' test | + '*' test ); + +comp_iter: comp_for | comp_if; +comp_for: ASYNC? 'for' exprlist 'in' or_test comp_iter?; +comp_if: 'if' test_nocond comp_iter?; + +// not used in grammar, but may appear in "node" passed from Parser to Compiler +encoding_decl: name; + +yield_expr: 'yield' yield_arg?; +yield_arg: 'from' test | testlist; + +strings: STRING+ ; diff --git a/languages/python-3/src/main/java/de/jplag/python3/JplagPython3Listener.java b/languages/python-3/src/main/java/de/jplag/python3/JplagPython3Listener.java index 59b987631..695d07e40 100644 --- a/languages/python-3/src/main/java/de/jplag/python3/JplagPython3Listener.java +++ b/languages/python-3/src/main/java/de/jplag/python3/JplagPython3Listener.java @@ -33,10 +33,10 @@ import org.antlr.v4.runtime.tree.TerminalNode; -import de.jplag.python3.grammar.Python3BaseListener; import de.jplag.python3.grammar.Python3Parser; +import de.jplag.python3.grammar.Python3ParserBaseListener; -public class JplagPython3Listener extends Python3BaseListener { +public class JplagPython3Listener extends Python3ParserBaseListener { private final Parser parser; @@ -56,7 +56,7 @@ public void enterDecorated(Python3Parser.DecoratedContext ctx) { @Override public void exitDecorated(Python3Parser.DecoratedContext ctx) { - parser.addEnd(DEC_END, ctx.getStart()); + parser.addEnd(DEC_END, ctx.getStop()); } @Override @@ -71,7 +71,7 @@ public void enterExcept_clause(Python3Parser.Except_clauseContext ctx) { @Override public void exitExcept_clause(Python3Parser.Except_clauseContext ctx) { - parser.addEnd(EXCEPT_END, ctx.getStart()); + parser.addEnd(EXCEPT_END, ctx.getStop()); } @Override @@ -91,7 +91,7 @@ public void enterWhile_stmt(Python3Parser.While_stmtContext ctx) { @Override public void exitWhile_stmt(Python3Parser.While_stmtContext ctx) { - parser.addEnd(WHILE_END, ctx.getStart()); + parser.addEnd(WHILE_END, ctx.getStop()); } @Override @@ -133,7 +133,7 @@ public void enterIf_stmt(Python3Parser.If_stmtContext ctx) { @Override public void exitIf_stmt(Python3Parser.If_stmtContext ctx) { - parser.addEnd(IF_END, ctx.getStart()); + parser.addEnd(IF_END, ctx.getStop()); } @Override @@ -143,7 +143,7 @@ public void enterWith_stmt(Python3Parser.With_stmtContext ctx) { @Override public void exitWith_stmt(Python3Parser.With_stmtContext ctx) { - parser.addEnd(WITH_END, ctx.getStart()); + parser.addEnd(WITH_END, ctx.getStop()); } @Override @@ -153,7 +153,7 @@ public void enterClassdef(Python3Parser.ClassdefContext ctx) { @Override public void exitClassdef(Python3Parser.ClassdefContext ctx) { - parser.addEnd(CLASS_END, ctx.getStart()); + parser.addEnd(CLASS_END, ctx.getStop()); } @Override @@ -172,7 +172,7 @@ public void enterFuncdef(Python3Parser.FuncdefContext ctx) { @Override public void exitFuncdef(Python3Parser.FuncdefContext ctx) { - parser.addEnd(METHOD_END, ctx.getStart()); + parser.addEnd(METHOD_END, ctx.getStop()); } @Override @@ -197,7 +197,7 @@ public void enterFor_stmt(Python3Parser.For_stmtContext ctx) { @Override public void exitFor_stmt(Python3Parser.For_stmtContext ctx) { - parser.addEnd(FOR_END, ctx.getStart()); + parser.addEnd(FOR_END, ctx.getStop()); } @Override diff --git a/languages/python-3/src/main/java/de/jplag/python3/Parser.java b/languages/python-3/src/main/java/de/jplag/python3/Parser.java index a24ccc15c..2dc352bfe 100644 --- a/languages/python-3/src/main/java/de/jplag/python3/Parser.java +++ b/languages/python-3/src/main/java/de/jplag/python3/Parser.java @@ -1,7 +1,7 @@ package de.jplag.python3; +import java.io.BufferedReader; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -19,6 +19,7 @@ import de.jplag.python3.grammar.Python3Lexer; import de.jplag.python3.grammar.Python3Parser; import de.jplag.python3.grammar.Python3Parser.File_inputContext; +import de.jplag.util.FileUtils; public class Parser extends AbstractParser { @@ -43,11 +44,11 @@ public List parse(Set files) throws ParsingException { } private void parseFile(File file) throws ParsingException { - try (FileInputStream fileInputStream = new FileInputStream((file))) { + try (BufferedReader reader = FileUtils.openFileReader(file)) { currentFile = file; // create a lexer that feeds off of input CharStream - Python3Lexer lexer = new Python3Lexer(CharStreams.fromStream(fileInputStream)); + Python3Lexer lexer = new Python3Lexer(CharStreams.fromReader(reader)); // create a buffer of tokens pulled from the lexer CommonTokenStream tokens = new CommonTokenStream(lexer); diff --git a/languages/python-3/src/main/java/de/jplag/python3/Python3TokenType.java b/languages/python-3/src/main/java/de/jplag/python3/Python3TokenType.java index a692031be..e4a684c9b 100644 --- a/languages/python-3/src/main/java/de/jplag/python3/Python3TokenType.java +++ b/languages/python-3/src/main/java/de/jplag/python3/Python3TokenType.java @@ -36,6 +36,7 @@ public enum Python3TokenType implements TokenType { private final String description; + @Override public String getDescription() { return this.description; } diff --git a/languages/python-3/src/main/java/de/jplag/python3/Language.java b/languages/python-3/src/main/java/de/jplag/python3/PythonLanguage.java similarity index 90% rename from languages/python-3/src/main/java/de/jplag/python3/Language.java rename to languages/python-3/src/main/java/de/jplag/python3/PythonLanguage.java index 8a35adaca..0140a37f7 100644 --- a/languages/python-3/src/main/java/de/jplag/python3/Language.java +++ b/languages/python-3/src/main/java/de/jplag/python3/PythonLanguage.java @@ -10,13 +10,13 @@ import de.jplag.Token; @MetaInfServices(de.jplag.Language.class) -public class Language implements de.jplag.Language { +public class PythonLanguage implements de.jplag.Language { private static final String IDENTIFIER = "python3"; private final Parser parser; - public Language() { + public PythonLanguage() { parser = new Parser(); } diff --git a/languages/python-3/src/main/java/de/jplag/python3/grammar/Python3LexerBase.java b/languages/python-3/src/main/java/de/jplag/python3/grammar/Python3LexerBase.java new file mode 100644 index 000000000..a60956d7c --- /dev/null +++ b/languages/python-3/src/main/java/de/jplag/python3/grammar/Python3LexerBase.java @@ -0,0 +1,134 @@ +package de.jplag.python3.grammar; + +import java.util.*; + +import org.antlr.v4.runtime.*; + +abstract class Python3LexerBase extends Lexer { + private LinkedList tokens = new LinkedList<>(); + private Deque indents = new LinkedList<>(); + private int opened = 0; + private Token lastToken = null; + + protected Python3LexerBase(CharStream input) { + super(input); + } + + @Override + public void emit(Token t) { + super.setToken(t); + tokens.offer(t); + } + + @Override + public Token nextToken() { + if (_input.LA(1) == EOF && !this.indents.isEmpty()) { + this.emit(commonToken(Python3Lexer.NEWLINE, "\n")); + this.removeTrailingEofTokens(); + + while (!indents.isEmpty()) { + this.emit(createDedent()); + indents.pop(); + } + + this.emit(commonToken(EOF, "")); + } + + Token next = super.nextToken(); + + if (next.getChannel() == Token.DEFAULT_CHANNEL) { + this.lastToken = next; + } + + return tokens.isEmpty() ? next : tokens.poll(); + } + + private void removeTrailingEofTokens() { + for (int i = tokens.size() - 1; i >= 0; i--) { + if (tokens.get(i).getType() == EOF) { + tokens.remove(i); + } + } + } + + private Token createDedent() { + CommonToken dedent = commonToken(Python3Lexer.DEDENT, ""); + dedent.setLine(this.lastToken.getLine()); + return dedent; + } + + private CommonToken commonToken(int type, String text) { + int stop = this.getCharIndex() - 1; + int start = text.isEmpty() ? stop : stop - text.length() + 1; + return new CommonToken(this._tokenFactorySourcePair, type, DEFAULT_TOKEN_CHANNEL, start, stop); + } + + /** + * Calculates the indentation of the provided spaces, taking the following rules into account: + *

+ * "Tabs are replaced (from left to right) by one to eight spaces such that the total number of characters up to and + * including the replacement is a multiple of eight [...]" + *

+ * -- https://docs.python.org/3.1/reference/lexical_analysis.html#indentation + **/ + static int getIndentationCount(String spaces) { + int count = 0; + for (char ch : spaces.toCharArray()) { + if (ch == '\t') { + count += 8 - (count % 8); + } else { + count++; + } + } + + return count; + } + + boolean atStartOfInput() { + return super.getCharPositionInLine() == 0 && super.getLine() == 1; + } + + void openBrace() { + this.opened++; + } + + void closeBrace() { + this.opened--; + } + + void onNewLine() { + String newLine = getText().replaceAll("[^\r\n\f]+", ""); + String spaces = getText().replaceAll("[\r\n\f]+", ""); + + int next = _input.LA(1); + int nextnext = _input.LA(2); + if (opened > 0 || (nextnext != -1 && (next == '\r' || next == '\n' || next == '\f' || next == '#'))) { + skip(); + } else { + emit(commonToken(Python3Lexer.NEWLINE, newLine)); + int indent = getIndentationCount(spaces); + int previous = indents.isEmpty() ? 0 : indents.peek(); + + if (indent == previous) { + skip(); + } else if (indent > previous) { + indents.push(indent); + emit(commonToken(Python3Lexer.INDENT, spaces)); + } else { + while (!indents.isEmpty() && indents.peek() > indent) { + this.emit(createDedent()); + indents.pop(); + } + } + } + } + + @Override + public void reset() { + tokens = new LinkedList<>(); + indents = new LinkedList<>(); + opened = 0; + lastToken = null; + super.reset(); + } +} diff --git a/languages/python-3/src/main/java/de/jplag/python3/grammar/Python3ParserBase.java b/languages/python-3/src/main/java/de/jplag/python3/grammar/Python3ParserBase.java new file mode 100644 index 000000000..327dd044c --- /dev/null +++ b/languages/python-3/src/main/java/de/jplag/python3/grammar/Python3ParserBase.java @@ -0,0 +1,17 @@ +package de.jplag.python3.grammar; + +import org.antlr.v4.runtime.*; + +public abstract class Python3ParserBase extends Parser { + protected Python3ParserBase(TokenStream input) { + super(input); + } + + public boolean cannotBePlusMinus() { + return true; + } + + public boolean cannotBeDotLpEq() { + return true; + } +} diff --git a/languages/python-3/src/test/java/de/jplag/python3/PythonLanguageCoverageTest.java b/languages/python-3/src/test/java/de/jplag/python3/PythonLanguageCoverageTest.java new file mode 100644 index 000000000..ada546e4b --- /dev/null +++ b/languages/python-3/src/test/java/de/jplag/python3/PythonLanguageCoverageTest.java @@ -0,0 +1,116 @@ +package de.jplag.python3; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.*; +import java.util.stream.Collectors; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import de.jplag.ParsingException; +import de.jplag.Token; +import de.jplag.TokenType; +import de.jplag.util.FileUtils; + +public class PythonLanguageCoverageTest { + private static final File testFileLocation = Path.of("src", "test", "resources", "de", "jplag", "python3").toFile(); + private static final String[] tokenCoverageFileNames = {"test_utils.py"}; + + private static final String[] lineIgnorePrefixes = {"else:", "elif", "#", "pass"}; + private static final String multilineStringMarker = "\"\"\""; + + private final PythonLanguage language = new PythonLanguage(); + + @ParameterizedTest + @MethodSource("collectSourceCoverageTestFiles") + void testSourceCoverage(File testFile) throws ParsingException, IOException { + List tokens = language.parse(Set.of(testFile)); + List lines = new ArrayList<>(getRelevantSourceFiles(testFile)); + + tokens.forEach(token -> lines.remove((Object) token.getLine())); + + if (!lines.isEmpty()) { + Assertions.fail("There were uncovered lines in: " + testFile.getPath() + "\n" + lines); + } + } + + @ParameterizedTest + @MethodSource("collectTokenCoverageTestFiles") + void testTokenCoverage(File testFile) throws ParsingException { + Set foundTokens = language.parse(Set.of(testFile)).stream().map(Token::getType).collect(Collectors.toSet()); + List allTokens = new ArrayList<>(List.of(Python3TokenType.values())); + + allTokens.removeAll(foundTokens); + + if (!allTokens.isEmpty()) { + Assertions.fail("There are token, that were not found in: " + testFile.getPath() + "\n" + allTokens); + } + } + + @ParameterizedTest + @MethodSource("collectSourceCoverageTestFiles") + void testMonotoneTokenOrder(File testFile) throws ParsingException { + List tokens = language.parse(Set.of(testFile)); + + for (int i = 0; i < tokens.size() - 2; i++) { + if (tokens.get(i).getLine() > tokens.get(i + 1).getLine()) { + Assertions.fail("Token " + tokens.get(i).getType() + " reported in line " + tokens.get(i).getLine() + + " has a bigger line index, than token " + tokens.get(i + 1).getType() + " in line " + tokens.get(i + 1).getLine()); + } + } + } + + public static List collectSourceCoverageTestFiles() { + return Arrays.asList(Objects.requireNonNull(testFileLocation.listFiles())); + } + + public static List collectTokenCoverageTestFiles() { + return Arrays.stream(tokenCoverageFileNames).map(it -> new File(testFileLocation, it)).toList(); + } + + private List getRelevantSourceFiles(File file) throws IOException { + List lines = FileUtils.readFileContent(file).lines().toList(); + List relevantLineIndices = new ArrayList<>(); + + boolean inMultilineString = false; + + for (int i = 0; i < lines.size(); i++) { + String line = lines.get(i); + if (!inMultilineString) { + if (isLineInlineIgnore(line)) { + continue; + } + + if (isMultilineStringStart(line)) { + inMultilineString = true; + continue; + } + } else { + if (isMultilineStringEnd(line)) { + inMultilineString = false; + } + continue; + } + + relevantLineIndices.add(i + 1); + } + + return relevantLineIndices; + } + + private boolean isLineInlineIgnore(String line) { + return line.isBlank() || Arrays.stream(lineIgnorePrefixes).anyMatch(it -> line.trim().startsWith(it)) + || (line.trim().startsWith(multilineStringMarker) && line.trim().substring(3).contains(multilineStringMarker)); + } + + private boolean isMultilineStringStart(String line) { + return line.trim().startsWith(multilineStringMarker); + } + + private boolean isMultilineStringEnd(String line) { + return line.trim().contains(multilineStringMarker); + } +} diff --git a/languages/python-3/src/test/java/de/jplag/python3/PythonLanguageSequenceTest.java b/languages/python-3/src/test/java/de/jplag/python3/PythonLanguageSequenceTest.java new file mode 100644 index 000000000..4ab5344da --- /dev/null +++ b/languages/python-3/src/test/java/de/jplag/python3/PythonLanguageSequenceTest.java @@ -0,0 +1,38 @@ +package de.jplag.python3; + +import java.io.File; +import java.nio.file.Path; +import java.util.List; +import java.util.Set; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import de.jplag.ParsingException; +import de.jplag.SharedTokenType; +import de.jplag.Token; +import de.jplag.TokenType; + +public class PythonLanguageSequenceTest { + private static final File testFileLocation = Path.of("src", "test", "resources", "de", "jplag", "python3").toFile(); + private final PythonLanguage language = new PythonLanguage(); + + @ParameterizedTest + @MethodSource("provideFileData") + void testTokenSequences(File file, TokenType[] sequence) throws ParsingException { + TokenType[] fileTokens = language.parse(Set.of(file)).stream().map(Token::getType).toArray(TokenType[]::new); + + Assertions.assertArrayEquals(sequence, fileTokens); + } + + public static List provideFileData() { + TokenType[] logTokens = new TokenType[] {Python3TokenType.IMPORT, Python3TokenType.ASSIGN, Python3TokenType.ARRAY, Python3TokenType.APPLY, + SharedTokenType.FILE_END}; + TokenType[] unicodeTokens = new TokenType[] {Python3TokenType.ASSIGN, SharedTokenType.FILE_END}; + + return List.of(Arguments.of(new File(testFileLocation, "log.py"), logTokens), + Arguments.of(new File(testFileLocation, "unicode.py"), unicodeTokens)); + } +} diff --git a/languages/python-3/src/test/resources/de/jplag/python3/base_features.py b/languages/python-3/src/test/resources/de/jplag/python3/base_features.py new file mode 100644 index 000000000..babad9a2b --- /dev/null +++ b/languages/python-3/src/test/resources/de/jplag/python3/base_features.py @@ -0,0 +1,70 @@ +__all__ = [] + +import concurrent.futures._base +import reprlib + +from . import events + +Error = concurrent.futures._base.Error +CancelledError = concurrent.futures.CancelledError +TimeoutError = concurrent.futures.TimeoutError + + +class InvalidStateError(Error): + """The operation is not allowed in this state.""" + + +# States for Future. +_PENDING = 'PENDING' +_CANCELLED = 'CANCELLED' +_FINISHED = 'FINISHED' + + +def isfuture(obj): + """Check for a Future. + + This returns True when obj is a Future instance or is advertising + itself as duck-type compatible by setting _asyncio_future_blocking. + See comment in Future for more details. + """ + return (hasattr(obj.__class__, '_asyncio_future_blocking') and + obj._asyncio_future_blocking is not None) + + +def _format_callbacks(cb): + """helper function for Future.__repr__""" + size = len(cb) + if not size: + cb = '' + + def format_cb(callback): + return events._format_callback_source(callback, ()) + + if size == 1: + cb = format_cb(cb[0]) + elif size == 2: + cb = '{}, {}'.format(format_cb(cb[0]), format_cb(cb[1])) + elif size > 2: + cb = '{}, <{} more>, {}'.format(format_cb(cb[0]), size - 2, + format_cb(cb[-1])) + return 'cb=[%s]' % cb + + +def _future_repr_info(future): + # (Future) -> str + """helper function for Future.__repr__""" + info = [future._state.lower()] + if future._state == _FINISHED: + if future._exception is not None: + info.append('exception={!r}'.format(future._exception)) + else: + # use reprlib to limit the length of the output, especially + # for very long strings + result = reprlib.repr(future._result) + info.append('result={}'.format(result)) + if future._callbacks: + info.append(_format_callbacks(future._callbacks)) + if future._source_traceback: + frame = future._source_traceback[-1] + info.append('created at %s:%s' % (frame[0], frame[1])) + return info diff --git a/languages/python-3/src/test/resources/de/jplag/python3/log.py b/languages/python-3/src/test/resources/de/jplag/python3/log.py new file mode 100644 index 000000000..23a7074af --- /dev/null +++ b/languages/python-3/src/test/resources/de/jplag/python3/log.py @@ -0,0 +1,7 @@ +"""Logging configuration.""" + +import logging + + +# Name the logger after the package. +logger = logging.getLogger(__package__) diff --git a/languages/python-3/src/test/resources/de/jplag/python3/streams.py b/languages/python-3/src/test/resources/de/jplag/python3/streams.py new file mode 100644 index 000000000..2941c6526 --- /dev/null +++ b/languages/python-3/src/test/resources/de/jplag/python3/streams.py @@ -0,0 +1,687 @@ +"""Stream-related things.""" + +__all__ = ['StreamReader', 'StreamWriter', 'StreamReaderProtocol', 'open_connection', 'start_server', 'IncompleteReadError', 'LimitOverrunError',] + +import socket + +if hasattr(socket, 'AF_UNIX'): + __all__.extend(['open_unix_connection', 'start_unix_server']) + +from . import coroutines +from . import compat +from . import events +from . import protocols +from .coroutines import coroutine +from .log import logger + + +_DEFAULT_LIMIT = 2 ** 16 + + +class IncompleteReadError(EOFError): + """ + Incomplete read error. Attributes: + + - partial: read bytes string before the end of stream was reached + - expected: total number of expected bytes (or None if unknown) + """ + def __init__(self, partial, expected): + super().__init__("%d bytes read on a total of %r expected bytes" + % (len(partial), expected)) + self.partial = partial + self.expected = expected + + +class LimitOverrunError(Exception): + """Reached the buffer limit while looking for a separator. + + Attributes: + - consumed: total number of to be consumed bytes. + """ + def __init__(self, message, consumed): + super().__init__(message) + self.consumed = consumed + + +@coroutine +def open_connection(host=None, port=None, *, + loop=None, limit=_DEFAULT_LIMIT, **kwds): + """A wrapper for create_connection() returning a (reader, writer) pair. + + The reader returned is a StreamReader instance; the writer is a + StreamWriter instance. + + The arguments are all the usual arguments to create_connection() + except protocol_factory; most common are positional host and port, + with various optional keyword arguments following. + + Additional optional keyword arguments are loop (to set the event loop + instance to use) and limit (to set the buffer limit passed to the + StreamReader). + + (If you want to customize the StreamReader and/or + StreamReaderProtocol classes, just copy the code -- there's + really nothing special here except some convenience.) + """ + if loop is None: + loop = events.get_event_loop() + reader = StreamReader(limit=limit, loop=loop) + protocol = StreamReaderProtocol(reader, loop=loop) + transport, _ = yield from loop.create_connection( + lambda: protocol, host, port, **kwds) + writer = StreamWriter(transport, protocol, reader, loop) + return reader, writer + + +@coroutine +def start_server(client_connected_cb, host=None, port=None, *, + loop=None, limit=_DEFAULT_LIMIT, **kwds): + """Start a socket server, call back for each client connected. + + The first parameter, `client_connected_cb`, takes two parameters: + client_reader, client_writer. client_reader is a StreamReader + object, while client_writer is a StreamWriter object. This + parameter can either be a plain callback function or a coroutine; + if it is a coroutine, it will be automatically converted into a + Task. + + The rest of the arguments are all the usual arguments to + loop.create_server() except protocol_factory; most common are + positional host and port, with various optional keyword arguments + following. The return value is the same as loop.create_server(). + + Additional optional keyword arguments are loop (to set the event loop + instance to use) and limit (to set the buffer limit passed to the + StreamReader). + + The return value is the same as loop.create_server(), i.e. a + Server object which can be used to stop the service. + """ + if loop is None: + loop = events.get_event_loop() + + def factory(): + reader = StreamReader(limit=limit, loop=loop) + protocol = StreamReaderProtocol(reader, client_connected_cb, + loop=loop) + return protocol + + return (yield from loop.create_server(factory, host, port, **kwds)) + + +if hasattr(socket, 'AF_UNIX'): + # UNIX Domain Sockets are supported on this platform + + @coroutine + def open_unix_connection(path=None, *, + loop=None, limit=_DEFAULT_LIMIT, **kwds): + """Similar to `open_connection` but works with UNIX Domain Sockets.""" + if loop is None: + loop = events.get_event_loop() + reader = StreamReader(limit=limit, loop=loop) + protocol = StreamReaderProtocol(reader, loop=loop) + transport, _ = yield from loop.create_unix_connection( + lambda: protocol, path, **kwds) + writer = StreamWriter(transport, protocol, reader, loop) + return reader, writer + + @coroutine + def start_unix_server(client_connected_cb, path=None, *, + loop=None, limit=_DEFAULT_LIMIT, **kwds): + """Similar to `start_server` but works with UNIX Domain Sockets.""" + if loop is None: + loop = events.get_event_loop() + + def factory(): + reader = StreamReader(limit=limit, loop=loop) + protocol = StreamReaderProtocol(reader, client_connected_cb, + loop=loop) + return protocol + + return (yield from loop.create_unix_server(factory, path, **kwds)) + + +class FlowControlMixin(protocols.Protocol): + """Reusable flow control logic for StreamWriter.drain(). + + This implements the protocol methods pause_writing(), + resume_reading() and connection_lost(). If the subclass overrides + these it must call the super methods. + + StreamWriter.drain() must wait for _drain_helper() coroutine. + """ + + def __init__(self, loop=None): + if loop is None: + self._loop = events.get_event_loop() + else: + self._loop = loop + self._paused = False + self._drain_waiter = None + self._connection_lost = False + + def pause_writing(self): + assert not self._paused + self._paused = True + if self._loop.get_debug(): + logger.debug("%r pauses writing", self) + + def resume_writing(self): + assert self._paused + self._paused = False + if self._loop.get_debug(): + logger.debug("%r resumes writing", self) + + waiter = self._drain_waiter + if waiter is not None: + self._drain_waiter = None + if not waiter.done(): + waiter.set_result(None) + + def connection_lost(self, exc): + self._connection_lost = True + # Wake up the writer if currently paused. + if not self._paused: + return + waiter = self._drain_waiter + if waiter is None: + return + self._drain_waiter = None + if waiter.done(): + return + if exc is None: + waiter.set_result(None) + else: + waiter.set_exception(exc) + + @coroutine + def _drain_helper(self): + if self._connection_lost: + raise ConnectionResetError('Connection lost') + if not self._paused: + return + waiter = self._drain_waiter + assert waiter is None or waiter.cancelled() + waiter = self._loop.create_future() + self._drain_waiter = waiter + yield from waiter + + +class StreamReaderProtocol(FlowControlMixin, protocols.Protocol): + """Helper class to adapt between Protocol and StreamReader. + + (This is a helper class instead of making StreamReader itself a + Protocol subclass, because the StreamReader has other potential + uses, and to prevent the user of the StreamReader to accidentally + call inappropriate methods of the protocol.) + """ + + def __init__(self, stream_reader, client_connected_cb=None, loop=None): + super().__init__(loop=loop) + self._stream_reader = stream_reader + self._stream_writer = None + self._client_connected_cb = client_connected_cb + self._over_ssl = False + + def connection_made(self, transport): + self._stream_reader.set_transport(transport) + self._over_ssl = transport.get_extra_info('sslcontext') is not None + if self._client_connected_cb is not None: + self._stream_writer = StreamWriter(transport, self, + self._stream_reader, + self._loop) + res = self._client_connected_cb(self._stream_reader, + self._stream_writer) + if coroutines.iscoroutine(res): + self._loop.create_task(res) + + def connection_lost(self, exc): + if self._stream_reader is not None: + if exc is None: + self._stream_reader.feed_eof() + else: + self._stream_reader.set_exception(exc) + super().connection_lost(exc) + self._stream_reader = None + self._stream_writer = None + + def data_received(self, data): + self._stream_reader.feed_data(data) + + def eof_received(self): + self._stream_reader.feed_eof() + if self._over_ssl: + # Prevent a warning in SSLProtocol.eof_received: + # "returning true from eof_received() + # has no effect when using ssl" + return False + return True + + +class StreamWriter: + """Wraps a Transport. + + This exposes write(), writelines(), [can_]write_eof(), + get_extra_info() and close(). It adds drain() which returns an + optional Future on which you can wait for flow control. It also + adds a transport property which references the Transport + directly. + """ + + def __init__(self, transport, protocol, reader, loop): + self._transport = transport + self._protocol = protocol + # drain() expects that the reader has an exception() method + assert reader is None or isinstance(reader, StreamReader) + self._reader = reader + self._loop = loop + + def __repr__(self): + info = [self.__class__.__name__, 'transport=%r' % self._transport] + if self._reader is not None: + info.append('reader=%r' % self._reader) + return '<%s>' % ' '.join(info) + + @property + def transport(self): + return self._transport + + def write(self, data): + self._transport.write(data) + + def writelines(self, data): + self._transport.writelines(data) + + def write_eof(self): + return self._transport.write_eof() + + def can_write_eof(self): + return self._transport.can_write_eof() + + def close(self): + return self._transport.close() + + def get_extra_info(self, name, default=None): + return self._transport.get_extra_info(name, default) + + @coroutine + def drain(self): + """Flush the write buffer. + + The intended use is to write + + w.write(data) + yield from w.drain() + """ + if self._reader is not None: + exc = self._reader.exception() + if exc is not None: + raise exc + if self._transport is not None: + if self._transport.is_closing(): + # Yield to the event loop so connection_lost() may be + # called. Without this, _drain_helper() would return + # immediately, and code that calls + # write(...); yield from drain() + # in a loop would never call connection_lost(), so it + # would not see an error when the socket is closed. + yield + yield from self._protocol._drain_helper() + + +class StreamReader: + + def __init__(self, limit=_DEFAULT_LIMIT, loop=None): + # The line length limit is a security feature; + # it also doubles as half the buffer limit. + + if limit <= 0: + raise ValueError('Limit cannot be <= 0') + + self._limit = limit + if loop is None: + self._loop = events.get_event_loop() + else: + self._loop = loop + self._buffer = bytearray() + self._eof = False # Whether we're done. + self._waiter = None # A future used by _wait_for_data() + self._exception = None + self._transport = None + self._paused = False + + def __repr__(self): + info = ['StreamReader'] + if self._buffer: + info.append('%d bytes' % len(self._buffer)) + if self._eof: + info.append('eof') + if self._limit != _DEFAULT_LIMIT: + info.append('l=%d' % self._limit) + if self._waiter: + info.append('w=%r' % self._waiter) + if self._exception: + info.append('e=%r' % self._exception) + if self._transport: + info.append('t=%r' % self._transport) + if self._paused: + info.append('paused') + return '<%s>' % ' '.join(info) + + def exception(self): + return self._exception + + def set_exception(self, exc): + self._exception = exc + + waiter = self._waiter + if waiter is not None: + self._waiter = None + if not waiter.cancelled(): + waiter.set_exception(exc) + + def _wakeup_waiter(self): + """Wakeup read*() functions waiting for data or EOF.""" + waiter = self._waiter + if waiter is not None: + self._waiter = None + if not waiter.cancelled(): + waiter.set_result(None) + + def set_transport(self, transport): + assert self._transport is None, 'Transport already set' + self._transport = transport + + def _maybe_resume_transport(self): + if self._paused and len(self._buffer) <= self._limit: + self._paused = False + self._transport.resume_reading() + + def feed_eof(self): + self._eof = True + self._wakeup_waiter() + + def at_eof(self): + """Return True if the buffer is empty and 'feed_eof' was called.""" + return self._eof and not self._buffer + + def feed_data(self, data): + assert not self._eof, 'feed_data after feed_eof' + + if not data: + return + + self._buffer.extend(data) + self._wakeup_waiter() + + if (self._transport is not None and + not self._paused and + len(self._buffer) > 2 * self._limit): + try: + self._transport.pause_reading() + except NotImplementedError: + # The transport can't be paused. + # We'll just have to buffer all data. + # Forget the transport so we don't keep trying. + self._transport = None + else: + self._paused = True + + @coroutine + def _wait_for_data(self, func_name): + """Wait until feed_data() or feed_eof() is called. + + If stream was paused, automatically resume it. + """ + # StreamReader uses a future to link the protocol feed_data() method + # to a read coroutine. Running two read coroutines at the same time + # would have an unexpected behaviour. It would not possible to know + # which coroutine would get the next data. + if self._waiter is not None: + raise RuntimeError('%s() called while another coroutine is already waiting for incoming data' % func_name) + + assert not self._eof, '_wait_for_data after EOF' + + # Waiting for data while paused will make deadlock, so prevent it. + # This is essential for readexactly(n) for case when n > self._limit. + if self._paused: + self._paused = False + self._transport.resume_reading() + + self._waiter = self._loop.create_future() + try: + yield from self._waiter + finally: + self._waiter = None + + @coroutine + def readline(self): + """Read chunk of data from the stream until newline (b'\n') is found. + + On success, return chunk that ends with newline. If only partial + line can be read due to EOF, return incomplete line without + terminating newline. When EOF was reached while no bytes read, empty + bytes object is returned. + + If limit is reached, ValueError will be raised. In that case, if + newline was found, complete line including newline will be removed + from internal buffer. Else, internal buffer will be cleared. Limit is + compared against part of the line without newline. + + If stream was paused, this function will automatically resume it if + needed. + """ + sep = b'\n' + seplen = len(sep) + try: + line = yield from self.readuntil(sep) + except IncompleteReadError as e: + return e.partial + except LimitOverrunError as e: + if self._buffer.startswith(sep, e.consumed): + del self._buffer[:e.consumed + seplen] + else: + self._buffer.clear() + self._maybe_resume_transport() + raise ValueError(e.args[0]) + return line + + @coroutine + def readuntil(self, separator=b'\n'): + """Read data from the stream until ``separator`` is found. + + On success, the data and separator will be removed from the + internal buffer (consumed). Returned data will include the + separator at the end. + + Configured stream limit is used to check result. Limit sets the + maximal length of data that can be returned, not counting the + separator. + + If an EOF occurs and the complete separator is still not found, + an IncompleteReadError exception will be raised, and the internal + buffer will be reset. The IncompleteReadError.partial attribute + may contain the separator partially. + + If the data cannot be read because of over limit, a + LimitOverrunError exception will be raised, and the data + will be left in the internal buffer, so it can be read again. + """ + seplen = len(separator) + if seplen == 0: + raise ValueError('Separator should be at least one-byte string') + + if self._exception is not None: + raise self._exception + + # Consume whole buffer except last bytes, which length is + # one less than seplen. Let's check corner cases with + # separator='SEPARATOR': + # * we have received almost complete separator (without last + # byte). i.e buffer='some textSEPARATO'. In this case we + # can safely consume len(separator) - 1 bytes. + # * last byte of buffer is first byte of separator, i.e. + # buffer='abcdefghijklmnopqrS'. We may safely consume + # everything except that last byte, but this require to + # analyze bytes of buffer that match partial separator. + # This is slow and/or require FSM. For this case our + # implementation is not optimal, since require rescanning + # of data that is known to not belong to separator. In + # real world, separator will not be so long to notice + # performance problems. Even when reading MIME-encoded + # messages :) + + # `offset` is the number of bytes from the beginning of the buffer + # where there is no occurrence of `separator`. + offset = 0 + + # Loop until we find `separator` in the buffer, exceed the buffer size, + # or an EOF has happened. + while True: + buflen = len(self._buffer) + + # Check if we now have enough data in the buffer for `separator` to + # fit. + if buflen - offset >= seplen: + isep = self._buffer.find(separator, offset) + + if isep != -1: + # `separator` is in the buffer. `isep` will be used later + # to retrieve the data. + break + + # see upper comment for explanation. + offset = buflen + 1 - seplen + if offset > self._limit: + raise LimitOverrunError('Separator is not found, and chunk exceed the limit', offset) + + # Complete message (with full separator) may be present in buffer + # even when EOF flag is set. This may happen when the last chunk + # adds data which makes separator be found. That's why we check for + # EOF *ater* inspecting the buffer. + if self._eof: + chunk = bytes(self._buffer) + self._buffer.clear() + raise IncompleteReadError(chunk, None) + + # _wait_for_data() will resume reading if stream was paused. + yield from self._wait_for_data('readuntil') + + if isep > self._limit: + raise LimitOverrunError('Separator is found, but chunk is longer than limit', isep) + + chunk = self._buffer[:isep + seplen] + del self._buffer[:isep + seplen] + self._maybe_resume_transport() + return bytes(chunk) + + @coroutine + def read(self, n=-1): + """Read up to `n` bytes from the stream. + + If n is not provided, or set to -1, read until EOF and return all read + bytes. If the EOF was received and the internal buffer is empty, return + an empty bytes object. + + If n is zero, return empty bytes object immediately. + + If n is positive, this function try to read `n` bytes, and may return + less or equal bytes than requested, but at least one byte. If EOF was + received before any byte is read, this function returns empty byte + object. + + Returned value is not limited with limit, configured at stream + creation. + + If stream was paused, this function will automatically resume it if + needed. + """ + + if self._exception is not None: + raise self._exception + + if n == 0: + return b'' + + if n < 0: + # This used to just loop creating a new waiter hoping to + # collect everything in self._buffer, but that would + # deadlock if the subprocess sends more than self.limit + # bytes. So just call self.read(self._limit) until EOF. + blocks = [] + while True: + block = yield from self.read(self._limit) + if not block: + break + blocks.append(block) + return b''.join(blocks) + + if not self._buffer and not self._eof: + yield from self._wait_for_data('read') + + # This will work right even if buffer is less than n bytes + data = bytes(self._buffer[:n]) + del self._buffer[:n] + + self._maybe_resume_transport() + return data + + @coroutine + def readexactly(self, n): + """Read exactly `n` bytes. + + Raise an IncompleteReadError if EOF is reached before `n` bytes can be + read. The IncompleteReadError.partial attribute of the exception will + contain the partial read bytes. + + if n is zero, return empty bytes object. + + Returned value is not limited with limit, configured at stream + creation. + + If stream was paused, this function will automatically resume it if + needed. + """ + if n < 0: + raise ValueError('readexactly size can not be less than zero') + + if self._exception is not None: + raise self._exception + + if n == 0: + return b'' + + while len(self._buffer) < n: + if self._eof: + incomplete = bytes(self._buffer) + self._buffer.clear() + raise IncompleteReadError(incomplete, n) + + yield from self._wait_for_data('readexactly') + + if len(self._buffer) == n: + data = bytes(self._buffer) + self._buffer.clear() + else: + data = bytes(self._buffer[:n]) + del self._buffer[:n] + self._maybe_resume_transport() + return data + + if compat.PY35: + @coroutine + def __aiter__(self): + return self + + @coroutine + def __anext__(self): + val = yield from self.readline() + if val == b'': + raise StopAsyncIteration + return val + + if compat.PY352: + # In Python 3.5.2 and greater, __aiter__ should return + # the asynchronous iterator directly. + def __aiter__(self): + return self diff --git a/languages/python-3/src/test/resources/de/jplag/python3/test_utils.py b/languages/python-3/src/test/resources/de/jplag/python3/test_utils.py new file mode 100644 index 000000000..34d92252c --- /dev/null +++ b/languages/python-3/src/test/resources/de/jplag/python3/test_utils.py @@ -0,0 +1,503 @@ +import collections +import contextlib +import io +import logging +import os +import re +import socket +import socketserver +import sys +import tempfile +import threading +import time +import unittest +import weakref + +from unittest import mock + +from http.server import HTTPServer +from wsgiref.simple_server import WSGIRequestHandler, WSGIServer + +try: + import ssl +except ImportError: # pragma: no cover + ssl = None + +from . import base_events +from . import compat +from . import events +from . import futures +from . import selectors +from . import tasks +from .coroutines import coroutine +from .log import logger + + +if sys.platform == 'win32': # pragma: no cover + from .windows_utils import socketpair +else: + from socket import socketpair # pragma: no cover + + +def dummy_ssl_context(): + if ssl is None: + return None + else: + return ssl.SSLContext(ssl.PROTOCOL_SSLv23) + + +def run_briefly(loop): + @coroutine + def once(): + pass + gen = once() + t = loop.create_task(gen) + # Don't log a warning if the task is not done after run_until_complete(). + # It occurs if the loop is stopped or if a task raises a BaseException. + t._log_destroy_pending = False + try: + loop.run_until_complete(t) + finally: + gen.close() + + +def run_until(loop, pred, timeout=30): + deadline = time.time() + timeout + while not pred(): + if timeout is not None: + timeout = deadline - time.time() + if timeout <= 0: + raise futures.TimeoutError() + loop.run_until_complete(tasks.sleep(0.001, loop=loop)) + + +def run_once(loop): + """Legacy API to run once through the event loop. + + This is the recommended pattern for test code. It will poll the + selector once and run all callbacks scheduled in response to I/O + events. + """ + loop.call_soon(loop.stop) + loop.run_forever() + + +class SilentWSGIRequestHandler(WSGIRequestHandler): + + def get_stderr(self): + return io.StringIO() + + def log_message(self, format, *args): + pass + + +class SilentWSGIServer(WSGIServer): + + request_timeout = 2 + + def get_request(self): + request, client_addr = super().get_request() + request.settimeout(self.request_timeout) + return request, client_addr + + def handle_error(self, request, client_address): + pass + + +class SSLWSGIServerMixin: + + def finish_request(self, request, client_address): + # The relative location of our test directory (which + # contains the ssl key and certificate files) differs + # between the stdlib and stand-alone asyncio. + # Prefer our own if we can find it. + here = os.path.join(os.path.dirname(__file__), '..', 'tests') + if not os.path.isdir(here): + here = os.path.join(os.path.dirname(os.__file__), 'test', 'test_asyncio') + keyfile = os.path.join(here, 'ssl_key.pem') + certfile = os.path.join(here, 'ssl_cert.pem') + context = ssl.SSLContext() + context.load_cert_chain(certfile, keyfile) + + ssock = context.wrap_socket(request, server_side=True) + try: + self.RequestHandlerClass(ssock, client_address, self) + ssock.close() + except OSError: + # maybe socket has been closed by peer + pass + + +class SSLWSGIServer(SSLWSGIServerMixin, SilentWSGIServer): + pass + + +def _run_test_server(*, address, use_ssl=False, server_cls, server_ssl_cls): + + def app(environ, start_response): + status = '200 OK' + headers = [('Content-type', 'text/plain')] + start_response(status, headers) + return [b'Test message'] + + # Run the test WSGI server in a separate thread in order not to + # interfere with event handling in the main thread + server_class = server_ssl_cls if use_ssl else server_cls + httpd = server_class(address, SilentWSGIRequestHandler) + httpd.set_app(app) + httpd.address = httpd.server_address + server_thread = threading.Thread( + target=lambda: httpd.serve_forever(poll_interval=0.05)) + server_thread.start() + try: + yield httpd + finally: + httpd.shutdown() + httpd.server_close() + server_thread.join() + + +if hasattr(socket, 'AF_UNIX'): + + class UnixHTTPServer(socketserver.UnixStreamServer, HTTPServer): + + def server_bind(self): + socketserver.UnixStreamServer.server_bind(self) + self.server_name = '127.0.0.1' + self.server_port = 80 + + + class UnixWSGIServer(UnixHTTPServer, WSGIServer): + + request_timeout = 2 + + def server_bind(self): + UnixHTTPServer.server_bind(self) + self.setup_environ() + + def get_request(self): + request, client_addr = super().get_request() + request.settimeout(self.request_timeout) + # Code in the stdlib expects that get_request + # will return a socket and a tuple (host, port). + # However, this isn't true for UNIX sockets, + # as the second return value will be a path; + # hence we return some fake data sufficient + # to get the tests going + return request, ('127.0.0.1', '') + + + class SilentUnixWSGIServer(UnixWSGIServer): + + def handle_error(self, request, client_address): + pass + + + class UnixSSLWSGIServer(SSLWSGIServerMixin, SilentUnixWSGIServer): + pass + + + def gen_unix_socket_path(): + with tempfile.NamedTemporaryFile() as file: + return file.name + + + @contextlib.contextmanager + def unix_socket_path(): + path = gen_unix_socket_path() + try: + yield path + finally: + try: + os.unlink(path) + except OSError: + pass + + + @contextlib.contextmanager + def run_test_unix_server(*, use_ssl=False): + with unix_socket_path() as path: + yield from _run_test_server(address=path, use_ssl=use_ssl, + server_cls=SilentUnixWSGIServer, + server_ssl_cls=UnixSSLWSGIServer) + + +@contextlib.contextmanager +def run_test_server(*, host='127.0.0.1', port=0, use_ssl=False): + yield from _run_test_server(address=(host, port), use_ssl=use_ssl, + server_cls=SilentWSGIServer, + server_ssl_cls=SSLWSGIServer) + + +def make_test_protocol(base): + dct = {} + for name in dir(base): + if name.startswith('__') and name.endswith('__'): + # skip magic names + continue + dct[name] = MockCallback(return_value=None) + return type('TestProtocol', (base,) + base.__bases__, dct)() + + +class TestSelector(selectors.BaseSelector): + + def __init__(self): + self.keys = {} + + def register(self, fileobj, events, data=None): + key = selectors.SelectorKey(fileobj, 0, events, data) + self.keys[fileobj] = key + return key + + def unregister(self, fileobj): + return self.keys.pop(fileobj) + + def select(self, timeout): + return [] + + def get_map(self): + return self.keys + + +class TestLoop(base_events.BaseEventLoop): + """Loop for unittests. + + It manages self time directly. + If something scheduled to be executed later then + on next loop iteration after all ready handlers done + generator passed to __init__ is calling. + + Generator should be like this: + + def gen(): + ... + when = yield ... + ... = yield time_advance + + Value returned by yield is absolute time of next scheduled handler. + Value passed to yield is time advance to move loop's time forward. + """ + + def __init__(self, gen=None): + super().__init__() + + if gen is None: + def gen(): + yield + self._check_on_close = False + else: + self._check_on_close = True + + self._gen = gen() + next(self._gen) + self._time = 0 + self._clock_resolution = 1e-9 + self._timers = [] + self._selector = TestSelector() + + self.readers = {} + self.writers = {} + self.reset_counters() + + self._transports = weakref.WeakValueDictionary() + + def time(self): + return self._time + + def advance_time(self, advance): + """Move test time forward.""" + if advance: + self._time += advance + + def close(self): + super().close() + if self._check_on_close: + try: + self._gen.send(0) + except StopIteration: + pass + else: # pragma: no cover + raise AssertionError("Time generator is not finished") + + def _add_reader(self, fd, callback, *args): + self.readers[fd] = events.Handle(callback, args, self) + + def _remove_reader(self, fd): + self.remove_reader_count[fd] += 1 + if fd in self.readers: + del self.readers[fd] + return True + else: + return False + + def assert_reader(self, fd, callback, *args): + assert fd in self.readers, 'fd {} is not registered'.format(fd) + handle = self.readers[fd] + assert handle._callback == callback, '{!r} != {!r}'.format( + handle._callback, callback) + assert handle._args == args, '{!r} != {!r}'.format( + handle._args, args) + + def _add_writer(self, fd, callback, *args): + self.writers[fd] = events.Handle(callback, args, self) + + def _remove_writer(self, fd): + self.remove_writer_count[fd] += 1 + if fd in self.writers: + del self.writers[fd] + return True + else: + return False + + def assert_writer(self, fd, callback, *args): + assert fd in self.writers, 'fd {} is not registered'.format(fd) + handle = self.writers[fd] + assert handle._callback == callback, '{!r} != {!r}'.format( + handle._callback, callback) + assert handle._args == args, '{!r} != {!r}'.format( + handle._args, args) + + def _ensure_fd_no_transport(self, fd): + try: + transport = self._transports[fd] + except KeyError: + pass + else: + raise RuntimeError( + 'File descriptor {!r} is used by transport {!r}'.format(fd, transport)) + + def add_reader(self, fd, callback, *args): + """Add a reader callback.""" + self._ensure_fd_no_transport(fd) + return self._add_reader(fd, callback, *args) + + def remove_reader(self, fd): + """Remove a reader callback.""" + self._ensure_fd_no_transport(fd) + return self._remove_reader(fd) + + def add_writer(self, fd, callback, *args): + """Add a writer callback..""" + self._ensure_fd_no_transport(fd) + return self._add_writer(fd, callback, *args) + + def remove_writer(self, fd): + """Remove a writer callback.""" + self._ensure_fd_no_transport(fd) + return self._remove_writer(fd) + + def reset_counters(self): + self.remove_reader_count = collections.defaultdict(int) + self.remove_writer_count = collections.defaultdict(int) + + def _run_once(self): + super()._run_once() + for when in self._timers: + advance = self._gen.send(when) + self.advance_time(advance) + self._timers = [] + + def call_at(self, when, callback, *args): + self._timers.append(when) + return super().call_at(when, callback, *args) + + def _process_events(self, event_list): + return + + def _write_to_self(self): + pass + + +def MockCallback(**kwargs): + return mock.Mock(spec=['__call__'], **kwargs) + + +class MockPattern(str): + """A regex based str with a fuzzy __eq__. + + Use this helper with 'mock.assert_called_with', or anywhere + where a regex comparison between strings is needed. + + For instance: + mock_call.assert_called_with(MockPattern('spam.*ham')) + """ + def __eq__(self, other): + return bool(re.search(str(self), other, re.S)) + + +def get_function_source(func): + source = events._get_function_source(func) + if source is None: + raise ValueError("unable to get the source of %r" % (func,)) + return source + + +class TestCase(unittest.TestCase): + def set_event_loop(self, loop, *, cleanup=True): + assert loop is not None + # ensure that the event loop is passed explicitly in asyncio + events.set_event_loop(None) + if cleanup: + self.addCleanup(loop.close) + + def new_test_loop(self, gen=None): + loop = TestLoop(gen) + self.set_event_loop(loop) + return loop + + def setUp(self): + self._get_running_loop = events._get_running_loop + events._get_running_loop = lambda: None + + def tearDown(self): + events._get_running_loop = self._get_running_loop + + events.set_event_loop(None) + + # Detect CPython bug #23353: ensure that yield/yield-from is not used + # in an except block of a generator + self.assertEqual(sys.exc_info(), (None, None, None)) + + if not compat.PY34: + # Python 3.3 compatibility + def subTest(self, *args, **kwargs): + class EmptyCM: + def __enter__(self): + pass + def __exit__(self, *exc): + pass + return EmptyCM() + + +@contextlib.contextmanager +def disable_logger(): + """Context manager to disable asyncio logger. + + For example, it can be used to ignore warnings in debug mode. + """ + old_level = logger.level + try: + logger.setLevel(logging.CRITICAL+1) + yield + finally: + logger.setLevel(old_level) + + +def mock_nonblocking_socket(proto=socket.IPPROTO_TCP, type=socket.SOCK_STREAM, + family=socket.AF_INET): + """Create a mock of a non-blocking socket.""" + sock = mock.MagicMock(socket.socket) + sock.proto = proto + sock.type = type + sock.family = family + sock.gettimeout.return_value = 0.0 + return sock + + +def force_legacy_ssl_support(): + return mock.patch('asyncio.sslproto._is_sslproto_available', + return_value=False) + +def switchWithBreak(): + while True: + break \ No newline at end of file diff --git a/languages/python-3/src/test/resources/de/jplag/python3/unicode.py b/languages/python-3/src/test/resources/de/jplag/python3/unicode.py new file mode 100644 index 000000000..48d384c81 --- /dev/null +++ b/languages/python-3/src/test/resources/de/jplag/python3/unicode.py @@ -0,0 +1 @@ +ไธ่ฆๅฟ˜่ฎฐๅฏ้›ชไผ˜่กฃ_Official=1 diff --git a/languages/rlang/README.md b/languages/rlang/README.md index bf1e06435..ee5294a9f 100644 --- a/languages/rlang/README.md +++ b/languages/rlang/README.md @@ -13,4 +13,4 @@ The choice of tokens is based directly on the CodeGra-de version, whereas the ex Like in other modules, e.g. for Java and C#, the tokens account for the beginning and the end of control flow structures, for control flow keywords, and some kinds of expressions. As R is very different from other programming languages in JPlag, it remains to be seen whether the R module can hold up to the others. ### Usage -To use the R module, add the `-l R` flag in the CLI, or use a `JPlagOption` object with `new de.jplag.rlang.Language()` as `language` in the Java API as described in the usage information in the [readme of the main project](https://github.com/jplag/JPlag#usage) and [in the wiki](https://github.com/jplag/JPlag/wiki/1.-How-to-Use-JPlag). \ No newline at end of file +To use the R module, add the `-l R` flag in the CLI, or use a `JPlagOption` object with `new RLanguage()` as `language` in the Java API as described in the usage information in the [readme of the main project](https://github.com/jplag/JPlag#usage) and [in the wiki](https://github.com/jplag/JPlag/wiki/1.-How-to-Use-JPlag). \ No newline at end of file diff --git a/languages/rlang/src/main/java/de/jplag/rlang/Language.java b/languages/rlang/src/main/java/de/jplag/rlang/RLanguage.java similarity index 93% rename from languages/rlang/src/main/java/de/jplag/rlang/Language.java rename to languages/rlang/src/main/java/de/jplag/rlang/RLanguage.java index a05abd066..182b856d2 100644 --- a/languages/rlang/src/main/java/de/jplag/rlang/Language.java +++ b/languages/rlang/src/main/java/de/jplag/rlang/RLanguage.java @@ -13,7 +13,7 @@ * This represents the R language as a language supported by JPlag. */ @MetaInfServices(de.jplag.Language.class) -public class Language implements de.jplag.Language { +public class RLanguage implements de.jplag.Language { private static final String NAME = "R Parser"; private static final String IDENTIFIER = "rlang"; @@ -21,7 +21,7 @@ public class Language implements de.jplag.Language { private static final String[] FILE_EXTENSION = {".R", ".r"}; private final RParserAdapter parserAdapter; - public Language() { + public RLanguage() { this.parserAdapter = new RParserAdapter(); } diff --git a/languages/rlang/src/main/java/de/jplag/rlang/RParserAdapter.java b/languages/rlang/src/main/java/de/jplag/rlang/RParserAdapter.java index 6da61e4c1..e3c3aa6bc 100644 --- a/languages/rlang/src/main/java/de/jplag/rlang/RParserAdapter.java +++ b/languages/rlang/src/main/java/de/jplag/rlang/RParserAdapter.java @@ -1,7 +1,7 @@ package de.jplag.rlang; +import java.io.BufferedReader; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -20,6 +20,7 @@ import de.jplag.rlang.grammar.RFilter; import de.jplag.rlang.grammar.RLexer; import de.jplag.rlang.grammar.RParser; +import de.jplag.util.FileUtils; /** * This class sets up the lexer and parser generated by ANTLR4, feeds the submissions through them and passes the @@ -52,11 +53,11 @@ public List parse(Set files) throws ParsingException { } private void parseFile(File file) throws ParsingException { - try (FileInputStream inputStream = new FileInputStream(file)) { + try (BufferedReader reader = FileUtils.openFileReader(file)) { currentFile = file; // create a lexer, a parser and a buffer between them. - RLexer lexer = new RLexer(CharStreams.fromStream(inputStream)); + RLexer lexer = new RLexer(CharStreams.fromReader(reader)); CommonTokenStream tokens = new CommonTokenStream(lexer); RFilter filter = new RFilter(tokens); diff --git a/languages/rlang/src/main/java/de/jplag/rlang/RTokenType.java b/languages/rlang/src/main/java/de/jplag/rlang/RTokenType.java index a70a08607..3a58935fb 100644 --- a/languages/rlang/src/main/java/de/jplag/rlang/RTokenType.java +++ b/languages/rlang/src/main/java/de/jplag/rlang/RTokenType.java @@ -35,6 +35,7 @@ public enum RTokenType implements TokenType { private final String description; + @Override public String getDescription() { return this.description; } diff --git a/languages/rlang/src/test/java/de/jplag/rlang/RLanguageTest.java b/languages/rlang/src/test/java/de/jplag/rlang/RLanguageTest.java index 21c9928d7..1479a44ea 100644 --- a/languages/rlang/src/test/java/de/jplag/rlang/RLanguageTest.java +++ b/languages/rlang/src/test/java/de/jplag/rlang/RLanguageTest.java @@ -39,11 +39,11 @@ class RLanguageTest { private final Logger logger = LoggerFactory.getLogger(RLanguageTest.class); private final String[] testFiles = new String[] {"Game.R", COMPLETE_TEST_FILE}; private final File testFileLocation = Path.of("src", "test", "resources", "de", "jplag", "rlang").toFile(); - private Language language; + private RLanguage language; @BeforeEach void setup() { - language = new Language(); + language = new RLanguage(); } @Test diff --git a/languages/rust/README.md b/languages/rust/README.md index 86427f54d..69a4af07e 100644 --- a/languages/rust/README.md +++ b/languages/rust/README.md @@ -88,6 +88,6 @@ Currently, macro rule definition bodies and macro macro invocation arguments/bod ### Usage To use the Rust module, add the `-l rust` flag in the CLI, or use a `JPlagOption` object -with `new de.jplag.rust.Language()` as `language` in the Java API as described in the usage information in +with `new de.jplag.rust.RustLanguage()` as `language` in the Java API as described in the usage information in the [readme of the main project](https://github.com/jplag/JPlag#usage) and [in the wiki](https://github.com/jplag/JPlag/wiki/1.-How-to-Use-JPlag). diff --git a/languages/rust/src/main/java/de/jplag/rust/Language.java b/languages/rust/src/main/java/de/jplag/rust/RustLanguage.java similarity index 92% rename from languages/rust/src/main/java/de/jplag/rust/Language.java rename to languages/rust/src/main/java/de/jplag/rust/RustLanguage.java index 2508d285f..72d8fb89f 100644 --- a/languages/rust/src/main/java/de/jplag/rust/Language.java +++ b/languages/rust/src/main/java/de/jplag/rust/RustLanguage.java @@ -13,7 +13,7 @@ * This represents the Rust language as a language supported by JPlag. */ @MetaInfServices(de.jplag.Language.class) -public class Language implements de.jplag.Language { +public class RustLanguage implements de.jplag.Language { protected static final String[] FILE_EXTENSIONS = {".rs"}; private static final String NAME = "Rust Language Module"; @@ -22,7 +22,7 @@ public class Language implements de.jplag.Language { private final RustParserAdapter parserAdapter; - public Language() { + public RustLanguage() { this.parserAdapter = new RustParserAdapter(); } diff --git a/languages/rust/src/main/java/de/jplag/rust/RustParserAdapter.java b/languages/rust/src/main/java/de/jplag/rust/RustParserAdapter.java index 5a4d9920c..092889054 100644 --- a/languages/rust/src/main/java/de/jplag/rust/RustParserAdapter.java +++ b/languages/rust/src/main/java/de/jplag/rust/RustParserAdapter.java @@ -1,7 +1,7 @@ package de.jplag.rust; +import java.io.BufferedReader; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -18,6 +18,7 @@ import de.jplag.Token; import de.jplag.rust.grammar.RustLexer; import de.jplag.rust.grammar.RustParser; +import de.jplag.util.FileUtils; public class RustParserAdapter extends AbstractParser { @@ -39,11 +40,11 @@ public List parse(Set files) throws ParsingException { } private void parseFile(File file) throws ParsingException { - try (FileInputStream inputStream = new FileInputStream(file)) { + try (BufferedReader reader = FileUtils.openFileReader(file)) { currentFile = file; // create a lexer, a parser and a buffer between them. - RustLexer lexer = new RustLexer(CharStreams.fromStream(inputStream)); + RustLexer lexer = new RustLexer(CharStreams.fromReader(reader)); CommonTokenStream tokenStream = new CommonTokenStream(lexer); RustParser parser = new RustParser(tokenStream); diff --git a/languages/rust/src/main/java/de/jplag/rust/RustTokenType.java b/languages/rust/src/main/java/de/jplag/rust/RustTokenType.java index 8e744c37b..4655b9525 100644 --- a/languages/rust/src/main/java/de/jplag/rust/RustTokenType.java +++ b/languages/rust/src/main/java/de/jplag/rust/RustTokenType.java @@ -114,6 +114,7 @@ public enum RustTokenType implements TokenType { private final String description; + @Override public String getDescription() { return description; } diff --git a/languages/rust/src/test/java/de/jplag/rust/RustLanguageTest.java b/languages/rust/src/test/java/de/jplag/rust/RustLanguageTest.java index 2e0d3e6f8..5d424d7ce 100644 --- a/languages/rust/src/test/java/de/jplag/rust/RustLanguageTest.java +++ b/languages/rust/src/test/java/de/jplag/rust/RustLanguageTest.java @@ -1,6 +1,7 @@ package de.jplag.rust; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; import java.io.File; import java.io.IOException; @@ -43,11 +44,11 @@ class RustLanguageTest { private final Logger logger = LoggerFactory.getLogger(RustLanguageTest.class); private final String[] testFiles = new String[] {"deno_core_runtime.rs", COMPLETE_TEST_FILE}; private final File testFileLocation = Path.of("src", "test", "resources", "de", "jplag", "rust").toFile(); - private Language language; + private RustLanguage language; @BeforeEach void setup() { - language = new Language(); + language = new RustLanguage(); } @Test @@ -93,7 +94,7 @@ private void testSourceCoverage(String fileName, List tokens) { } catch (IOException exception) { logger.info("Error while reading test file %s".formatted(fileName), exception); - assertTrue(false); + fail(); } } diff --git a/languages/scala/pom.xml b/languages/scala/pom.xml index 0f36b9853..c768e9edb 100644 --- a/languages/scala/pom.xml +++ b/languages/scala/pom.xml @@ -10,7 +10,7 @@ scala - 2.13.10 + 2.13.12 2.13 @@ -25,7 +25,7 @@ org.scalameta scalameta_${scala.compat.version} - 4.6.0 + 4.8.12 diff --git a/languages/scala/src/main/resources/META-INF/services/de.jplag.Language b/languages/scala/src/main/resources/META-INF/services/de.jplag.Language index 9daa29f0d..506c27730 100644 --- a/languages/scala/src/main/resources/META-INF/services/de.jplag.Language +++ b/languages/scala/src/main/resources/META-INF/services/de.jplag.Language @@ -1 +1 @@ -de.jplag.scala.Language +de.jplag.scala.ScalaLanguage diff --git a/languages/scala/src/main/scala/de/jplag/scala/Parser.scala b/languages/scala/src/main/scala/de/jplag/scala/Parser.scala index c4436eb5e..b3fe9b3dc 100644 --- a/languages/scala/src/main/scala/de/jplag/scala/Parser.scala +++ b/languages/scala/src/main/scala/de/jplag/scala/Parser.scala @@ -1,10 +1,13 @@ package de.jplag.scala import de.jplag.scala.ScalaTokenType._ +import de.jplag.util.FileUtils import de.jplag.{AbstractParser, ParsingException, Token} import java.io.File +import java.util.stream.Collectors import scala.collection.mutable.ListBuffer +import scala.meta.Member.ParamClauseGroup import scala.meta._ @@ -132,8 +135,10 @@ class Parser extends AbstractParser { maybeAddAndApply(finallyExpression, FINALLY) }) - case Term.Apply(function, arguments) if !isStandardOperator(getMethodIdentifier(function)) && arguments.nonEmpty => + case call: Term.Apply if !isStandardOperator(getMethodIdentifier(call.fun)) && call.argClause.nonEmpty => // function calls with no arguments are not covered here; see README + val function = call.fun + val arguments = call.argClause TR(traverse = _ => { add(APPLY, function, fromEnd = false) @@ -151,12 +156,12 @@ class Parser extends AbstractParser { }) case Term.NewAnonymous(_) => TR(Some(NEW_CREATION_BEGIN), Some(NEW_CREATION_END)) case Term.Return(_) => TR(Some(RETURN)) - case Term.Match(expression, cases) => TR(Some(MATCH_BEGIN), Some(MATCH_END), traverse = _ => { - apply(expression) - processCases(cases) + case matchTerm: Term.Match => TR(Some(MATCH_BEGIN), Some(MATCH_END), traverse = _ => { + apply(matchTerm.expr) + processCases(matchTerm.cases) }) case Term.Throw(_) => TR(Some(THROW)) - case Term.Function(_) => TR(Some(FUNCTION_BEGIN), Some(FUNCTION_END)) + case _: Term.Function => TR(Some(FUNCTION_BEGIN), Some(FUNCTION_END)) case Term.PartialFunction(cases) => TR(Some(PARTIAL_FUNCTION_BEGIN), Some(PARTIAL_FUNCTION_END), traverse = _ => { processCases(cases) }) @@ -165,7 +170,11 @@ class Parser extends AbstractParser { add(FOR_BODY_BEGIN, body, fromEnd = false) encloseAndApply(body, TR(Some(YIELD), Some(FOR_BODY_END))) }) - case Term.If(condition, thenExpression, elseExpression) => TR(traverse = _ => { + case ifTerm: Term.If => TR(traverse = _ => { + val condition = ifTerm.cond + val thenExpression = ifTerm.thenp + val elseExpression = ifTerm.elsep + add(IF, tree, fromEnd = false) apply(condition) @@ -184,30 +193,30 @@ class Parser extends AbstractParser { case scala.meta.Pkg(_) => TR(Some(PACKAGE)) case scala.meta.Import(_) => TR(Some(IMPORT)) - case Defn.Def(modifiers, name, typeParameters, parameterLists, _, body) => + case definition: Defn.Def => TR(traverse = _ => { - applyRecursively(modifiers) - add(METHOD_DEF, name, fromEnd = false) - assignRecursively(typeParameters, TYPE_PARAMETER) - assignRecursively(parameterLists, PARAMETER) + applyRecursively(definition.mods) + add(METHOD_DEF, definition.name, fromEnd = false) + assignRecursively(getTParams(definition.paramClauseGroups), TYPE_PARAMETER) + assignRecursively(getPParamsLists(definition.paramClauseGroups), PARAMETER) - encloseAndApply(body, TR(Some(METHOD_BEGIN), Some(METHOD_END))) + encloseAndApply(definition.body, TR(Some(METHOD_BEGIN), Some(METHOD_END))) }) - case Defn.Macro(modifiers, _, typeParameters, parameterLists, _, body) => TR(Some(MACRO), traverse = _ => { - applyRecursively(Seq(modifiers, typeParameters, parameterLists)) - encloseAndApply(body, TR(Some(MACRO_BEGIN), Some(MACRO_END))) + case macroDef: Defn.Macro => TR(Some(MACRO), traverse = _ => { + applyRecursively(Seq(macroDef.mods, getTParams(macroDef.paramClauseGroups), getPParamsLists(macroDef.paramClauseGroups))) + encloseAndApply(macroDef.body, TR(Some(MACRO_BEGIN), Some(MACRO_END))) }) - case Defn.Class(_) => + case _: Defn.Class => TR(Some(CLASS_BEGIN), Some(CLASS_END)) case Defn.Object(_) => TR(Some(OBJECT_BEGIN), Some(OBJECT_END)) - case Defn.Trait(_) => TR(Some(TRAIT_BEGIN), Some(TRAIT_END)) - case Defn.Type(_) => TR(Some(TYPE)) - case Defn.Var(modifiers, patterns, declaredType, optionalValue) => TR(traverse = _ => { - apply(modifiers) - for (pattern <- patterns) { - handleDefinitionPattern(pattern, optionalValue) + case _: Defn.Trait => TR(Some(TRAIT_BEGIN), Some(TRAIT_END)) + case _: Defn.Type => TR(Some(TYPE)) + case varDef: Defn.Var => TR(traverse = _ => { + apply(varDef.mods) + for (pattern <- varDef.pats) { + handleDefinitionPattern(pattern, Some(varDef.body)) } - apply(declaredType) + apply(varDef.decltpe) }) case Defn.Val(modifiers, patterns, declaredType, value) => TR(traverse = _ => { apply(modifiers) @@ -220,24 +229,24 @@ class Parser extends AbstractParser { case Decl.Var(_) => TR(Some(VARIABLE_DEFINITION)) case Decl.Val(_) => TR(Some(VARIABLE_DEFINITION)) - case Decl.Def(_) => TR(Some(METHOD_BEGIN), Some(METHOD_END)) - case Decl.Type(_) => TR(Some(TYPE)) + case _: Decl.Def => TR(Some(METHOD_BEGIN), Some(METHOD_END)) + case _: Decl.Type => TR(Some(TYPE)) - case Ctor.Secondary(_) => + case _: Ctor.Secondary => TR(Some(CONSTRUCTOR_BEGIN), Some(CONSTRUCTOR_END)) - case Init(_, _, argumentLists) if argumentLists.nonEmpty => TR(traverse = _ => { - assignRecursively(argumentLists, ARGUMENT, doApply = true) + case init: Init if getArgLists(init.argClauses).nonEmpty => TR(traverse = _ => { + assignRecursively(getArgLists(init.argClauses), ARGUMENT, doApply = true) }) case Enumerator.Guard(_) => TR(Some(GUARD)) case Term.Param(_) => TR(traverse = _ => add(PARAMETER, tree, fromEnd = false)) - case Term.ApplyInfix(_, operator, _, _) if operator.value.contains("=") && !Array("==", "!=").contains(operator.value) => TR(Some(ASSIGN)) - case Term.ApplyInfix(function, operator, typeArgs, arguments) if !isStandardOperator(operator.value) => TR(traverse = _ => { + case term: Term.ApplyInfix if term.op.value.contains("=") && !Array("==", "!=").contains(term.op.value) => TR(Some(ASSIGN)) + case term: Term.ApplyInfix if !isStandardOperator(term.op.value) => TR(traverse = _ => { add(APPLY, tree, fromEnd = false) - apply(function) - assignRecursively(typeArgs, TYPE_ARGUMENT, doApply = true) - assignRecursively(arguments, ARGUMENT, doApply = true) + apply(term.lhs) + assignRecursively(term.targClause.values, TYPE_ARGUMENT, doApply = true) + assignRecursively(term.argClause.values, ARGUMENT, doApply = true) }) case Term.Select(refObj, member) => TR(traverse = _ => { @@ -245,20 +254,20 @@ class Parser extends AbstractParser { if (!isStandardOperator(member.value)) add(MEMBER, member, fromEnd = false) apply(member) }) - case Term.ApplyType(_, typeArgs) => TR(traverse = _ => { + case term: Term.ApplyType => TR(traverse = _ => { add(APPLY, tree, fromEnd = false) - assignRecursively(typeArgs, TYPE_ARGUMENT) + assignRecursively(term.targClause.values, TYPE_ARGUMENT) }) case Term.New(_) => TR(Some(NEW_OBJECT)) case Self(_) => TR(Some(SELF_TYPE)) - case block@Term.Block(_) => block.parent match { + case block@Term.Block(_) => block.parent.get.parent match { // inner block - case Some(Term.Apply(_)) => TR(Some(BLOCK_START), Some(BLOCK_END)) + case _: Some[Term.Apply] => TR(Some(BLOCK_START), Some(BLOCK_END)) // block in an expression context, e.g. for, if, while case _ => TR() } case Enumerator.Generator(_) => TR(Some(ENUM_GENERATOR)) - case meta.Type.Param(_) => TR(Some(TYPE_PARAMETER)) + case _: meta.Type.Param => TR(Some(TYPE_PARAMETER)) case _ => TR() } @@ -343,8 +352,7 @@ class Parser extends AbstractParser { currentFile = file try { - val bytes = java.nio.file.Files.readAllBytes(file.toPath) - val text = new String(bytes, "UTF-8") + val text = FileUtils.readFileContent(file) val input = Input.VirtualFile(file.getPath, text) val ast = input.parse[Source].get traverser(ast) @@ -389,4 +397,15 @@ class Parser extends AbstractParser { } } + private def getTParams(groups: List[ParamClauseGroup]): List[Type.Param] = { + groups.flatMap(it => it.tparamClause.values) + } + + private def getPParamsLists(groups: List[ParamClauseGroup]): List[List[Term.Param]] = { + groups.flatMap(it => it.paramClauses.map(clause => clause.values)) + } + + private def getArgLists(arguments: Seq[Term.ArgClause]): List[List[Term]] = { + arguments.map(it => it.values).toList + } } \ No newline at end of file diff --git a/languages/scala/src/main/scala/de/jplag/scala/Language.scala b/languages/scala/src/main/scala/de/jplag/scala/ScalaLanguage.scala similarity index 92% rename from languages/scala/src/main/scala/de/jplag/scala/Language.scala rename to languages/scala/src/main/scala/de/jplag/scala/ScalaLanguage.scala index c7c8be60c..47988c6d9 100644 --- a/languages/scala/src/main/scala/de/jplag/scala/Language.scala +++ b/languages/scala/src/main/scala/de/jplag/scala/ScalaLanguage.scala @@ -8,7 +8,7 @@ import org.kohsuke.MetaInfServices import java.util import scala.jdk.CollectionConverters.{SeqHasAsJava, SetHasAsScala} -class Language extends de.jplag.Language { +class ScalaLanguage extends de.jplag.Language { private val parser = new Parser private final val fileExtensions = Array(".scala", ".sc") diff --git a/languages/scala/src/main/scala/de/jplag/scala/ScalaTokenType.java b/languages/scala/src/main/scala/de/jplag/scala/ScalaTokenType.java index a21a5980e..a84255d91 100644 --- a/languages/scala/src/main/scala/de/jplag/scala/ScalaTokenType.java +++ b/languages/scala/src/main/scala/de/jplag/scala/ScalaTokenType.java @@ -74,6 +74,7 @@ public enum ScalaTokenType implements TokenType { private final String description; + @Override public String getDescription() { return description; } diff --git a/languages/scala/src/test/java/de/jplag/scala/ScalaLanguageTest.java b/languages/scala/src/test/java/de/jplag/scala/ScalaLanguageTest.java index 9daf3c5b1..fc659f083 100644 --- a/languages/scala/src/test/java/de/jplag/scala/ScalaLanguageTest.java +++ b/languages/scala/src/test/java/de/jplag/scala/ScalaLanguageTest.java @@ -49,11 +49,11 @@ class ScalaLanguageTest { private final Logger logger = LoggerFactory.getLogger(ScalaLanguageTest.class); private final String[] testFiles = new String[] {"Parser.scala", COMPLETE_TEST_FILE}; private final File testFileLocation = Path.of("src", "test", "resources", "de", "jplag", "scala").toFile(); - private Language language; + private ScalaLanguage language; @BeforeEach void setup() { - language = new Language(); + language = new ScalaLanguage(); } @Test @@ -110,7 +110,7 @@ private void testSourceCoverage(String fileName, List tokens) { /** * Gets the line numbers of lines containing actual code, omitting empty lines and comment lines. * @param lines lines of a code file - * @return an array of the line numbers of code lines + * @return a list of the line numbers of code lines */ private List getCodeLines(List lines) { // This boxed boolean can be accessed from within the lambda method below diff --git a/languages/scheme/src/main/java/de/jplag/scheme/Language.java b/languages/scheme/src/main/java/de/jplag/scheme/SchemeLanguage.java similarity index 90% rename from languages/scheme/src/main/java/de/jplag/scheme/Language.java rename to languages/scheme/src/main/java/de/jplag/scheme/SchemeLanguage.java index c5a1b53ac..08dec1df8 100644 --- a/languages/scheme/src/main/java/de/jplag/scheme/Language.java +++ b/languages/scheme/src/main/java/de/jplag/scheme/SchemeLanguage.java @@ -10,12 +10,12 @@ import de.jplag.Token; @MetaInfServices(de.jplag.Language.class) -public class Language implements de.jplag.Language { +public class SchemeLanguage implements de.jplag.Language { private static final String IDENTIFIER = "scheme"; private final de.jplag.scheme.Parser parser; - public Language() { + public SchemeLanguage() { parser = new Parser(); } diff --git a/languages/scheme/src/main/java/de/jplag/scheme/SchemeTokenType.java b/languages/scheme/src/main/java/de/jplag/scheme/SchemeTokenType.java index 8b2109ee1..a041d46d8 100644 --- a/languages/scheme/src/main/java/de/jplag/scheme/SchemeTokenType.java +++ b/languages/scheme/src/main/java/de/jplag/scheme/SchemeTokenType.java @@ -47,6 +47,7 @@ public enum SchemeTokenType implements TokenType { private final String description; + @Override public String getDescription() { return this.description; } diff --git a/languages/scheme/src/main/javacc/Scheme.jj b/languages/scheme/src/main/javacc/Scheme.jj index de2797daf..9d09407d8 100644 --- a/languages/scheme/src/main/javacc/Scheme.jj +++ b/languages/scheme/src/main/javacc/Scheme.jj @@ -58,7 +58,11 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.charset.Charset; + import de.jplag.ParsingException; +import de.jplag.util.FileUtils; public class SchemeParser { /* used for context in the template production rule */ @@ -68,15 +72,18 @@ public class SchemeParser { public static void parseFile(File file, SchemeParser parser, Parser parserX) throws ParsingException { try { FileInputStream in = new FileInputStream(file); + Charset charset = FileUtils.detectCharset(file); if (parser == null) { - parser = new SchemeParser(in, "UTF-8"); + parser = new SchemeParser(in, charset.name()); } else { - parser.ReInit(in, "UTF-8"); + parser.ReInit(in, charset.name()); } parser.parser2 = parserX; } catch (FileNotFoundException e) { System.out.println("Scheme Parser R4RS: File " + file.getName() + " not found."); throw new ParsingException(file, e.getMessage(), e); + } catch (IOException e) { + throw new ParsingException(file, e.getMessage(), e); } try { parser.Program(); diff --git a/languages/scxml/README.md b/languages/scxml/README.md new file mode 100644 index 000000000..ed8bb692b --- /dev/null +++ b/languages/scxml/README.md @@ -0,0 +1,22 @@ +## SCXML language module + +This language module enables the use of JPlag with SCXML submissions. +It works by first parsing the XML files using a SAX parser and transforming them into an intermediate Java object +structure. The tokens are extracted by iterating over this structure. + +### Token Extraction + +There are two token extraction strategies available: the SimpleStatechartTokenGenerator and the +HandcraftedStatechartTokenGenerator. The active strategy can be set by + +The SimpleStatechartTokenGenerator extracts tokens by recursively traversing the +Statechart object, using the elements outlined in the [SCXML specification](https://www.w3.org/TR/scxml). +The HandcraftedStatechartTokenGenerator utilizes a larger token set and extracts tokens based on the attributes of the +statechart element, for example extracting a `PARALLEL_STATE` token for a State if it is parallel. + +The set of possible tokens can be found here: +https://github.com/jplag/JPlag/blob/develop/languages/scxml/src/main/java/de/jplag/scxml/ScxmlTokenType.java + +## Usage + +To use the new module, add the `-l scxml` flag in the CLI. diff --git a/languages/scxml/pom.xml b/languages/scxml/pom.xml new file mode 100644 index 000000000..415ebd668 --- /dev/null +++ b/languages/scxml/pom.xml @@ -0,0 +1,19 @@ + + + 4.0.0 + + de.jplag + languages + ${revision} + + scxml + + + + org.assertj + assertj-core + 3.24.2 + test + + + diff --git a/languages/scxml/src/main/java/de/jplag/scxml/ScxmlLanguage.java b/languages/scxml/src/main/java/de/jplag/scxml/ScxmlLanguage.java new file mode 100644 index 000000000..6d83703e6 --- /dev/null +++ b/languages/scxml/src/main/java/de/jplag/scxml/ScxmlLanguage.java @@ -0,0 +1,79 @@ +package de.jplag.scxml; + +import java.io.File; +import java.util.List; +import java.util.Set; + +import org.kohsuke.MetaInfServices; + +import de.jplag.ParsingException; +import de.jplag.Token; +import de.jplag.scxml.parser.ScxmlParserAdapter; + +/** + * Language for statecharts in the State Chart XML (SCXML) format. + */ +@MetaInfServices(de.jplag.Language.class) +public class ScxmlLanguage implements de.jplag.Language { + + /** + * The file ending of SCXML statechart files. + */ + public static final String FILE_ENDING = ".scxml"; + + /** + * The file ending of view files. + */ + public static final String VIEW_FILE_SUFFIX = ".scxmlview"; + + private static final String NAME = "SCXML (Statechart XML)"; + private static final String IDENTIFIER = "scxml"; + private static final int DEFAULT_MIN_TOKEN_MATCH = 6; + + /** + * The parser adapter to use for parsing and extracting tokens from statecharts. + */ + protected final ScxmlParserAdapter parser; + + /** + * Constructs a new language instance for SCXML statecharts. + */ + public ScxmlLanguage() { + this.parser = new ScxmlParserAdapter(); + } + + @Override + public String[] suffixes() { + return new String[] {FILE_ENDING}; + } + + @Override + public String getName() { + return NAME; + } + + @Override + public String getIdentifier() { + return IDENTIFIER; + } + + @Override + public int minimumTokenMatch() { + return DEFAULT_MIN_TOKEN_MATCH; + } + + @Override + public List parse(Set files) throws ParsingException { + return parser.parse(files); + } + + @Override + public boolean useViewFiles() { + return true; + } + + @Override + public String viewFileSuffix() { + return VIEW_FILE_SUFFIX; + } +} diff --git a/languages/scxml/src/main/java/de/jplag/scxml/ScxmlToken.java b/languages/scxml/src/main/java/de/jplag/scxml/ScxmlToken.java new file mode 100644 index 000000000..13035cf49 --- /dev/null +++ b/languages/scxml/src/main/java/de/jplag/scxml/ScxmlToken.java @@ -0,0 +1,47 @@ +package de.jplag.scxml; + +import java.io.File; + +import de.jplag.Token; +import de.jplag.TokenType; +import de.jplag.scxml.parser.model.StatechartElement; + +/** + * Represents a SCXML token. + */ +public class ScxmlToken extends Token { + + private final StatechartElement element; + + /** + * Creates an SCXML token that corresponds to a StatechartElement. + * @param type the type of the token + * @param file the source statechart file + * @param element the corresponding StatechartElement this token was extracted from + */ + public ScxmlToken(TokenType type, File file, StatechartElement element) { + super(type, file, NO_VALUE, NO_VALUE, NO_VALUE); + this.element = element; + } + + /** + * Creates an SCXML token that corresponds to a StatechartElement including file information. + * @param type the type of the token + * @param file the source statechart file + * @param line the line index in the source code where the token resides, 1-based + * @param column the column index, meaning where the token starts in the line, 1-based + * @param length the length of the token in the view file + * @param element the corresponding StatechartElement this token was extracted from + */ + public ScxmlToken(TokenType type, File file, int line, int column, int length, StatechartElement element) { + super(type, file, line, column, length); + this.element = element; + } + + /** + * @return the StatechartElement corresponding to the token + */ + public StatechartElement getStatechartElement() { + return element; + } +} diff --git a/languages/scxml/src/main/java/de/jplag/scxml/ScxmlTokenType.java b/languages/scxml/src/main/java/de/jplag/scxml/ScxmlTokenType.java new file mode 100644 index 000000000..ad99427cb --- /dev/null +++ b/languages/scxml/src/main/java/de/jplag/scxml/ScxmlTokenType.java @@ -0,0 +1,167 @@ +package de.jplag.scxml; + +import de.jplag.TokenType; + +/** + * SCXML token type. Defines which tokens can be extracted from a statechart. + */ +public enum ScxmlTokenType implements TokenType { + + /** + * Token for a transition. + */ + TRANSITION("Transition"), + + /** + * Token extracted after visiting all child elements of a transition. + */ + TRANSITION_END("Transition end", true), + + /** + * Token for a guarded transition. + */ + GUARDED_TRANSITION("Guarded transition"), + + /** + * Token for a timed transition. + */ + TIMED_TRANSITION("Timed transition"), + + /** + * Token for a state. + */ + STATE("State"), + + /** + * Token for an initial state. + */ + INITIAL_STATE("Initial state"), + + /** + * Token extracted after visiting all child elements of a state. + */ + STATE_END("State end", true), + + /** + * Token for a region. + */ + REGION("Region"), + + /** + * Token for an initial region. + */ + INITIAL_REGION("Initial region"), + + /** + * Token for an OnEntry action. + */ + ON_ENTRY("OnEntry"), + + /** + * Token for an OnExit action. + */ + ON_EXIT("OnExit"), + + /** + * Token extracted after visiting all executable contents of an action (OnEntry or OnExit). + */ + ACTION_END("Action end", true), + + /** + * Token for the executable content raise. + */ + RAISE("Raise"), + + /** + * Token for the executable content if. + */ + IF("If"), + + /** + * Token extracted at the end of the executable content if. + */ + IF_END("If end", true), + + /** + * Token for the executable content raise. + */ + ELSE_IF("Else if"), + + /** + * Token for the end of a branch (else if or else). + */ + ELSE_IF_END("Branch end", true), + + /** + * Token for an else action. + */ + ELSE("Else"), + + /** + * Token for the end of an else action. + */ + ELSE_END("Else end", true), + + /** + * Token for the executable content foreach. + */ + FOREACH("For each"), + + /** + * Token for the executable content assignment. + */ + ASSIGNMENT("Assignment"), + + /** + * Token for the executable content foreach. + */ + CANCEL("Cancel"), + + /** + * Token for the executable content script. + */ + SCRIPT("Script"), + + /** + * Token for the executable content send. + */ + SEND("Send"); + + private final String description; + private boolean isEndToken = false; + + /** + * Constructs a new SCXML token type with a description. + * @param description the description for this token type + */ + ScxmlTokenType(String description) { + this.description = description; + } + + /** + * Creates a statechart token type that may be an end token. An end token represents a token that is always added after + * all child tokens for a nested token such as STATE. + * @param description the description for this token type + * @param isEndToken indicates that the token is an end token + */ + ScxmlTokenType(String description, boolean isEndToken) { + this(description); + this.isEndToken = isEndToken; + } + + /** + * @return the description for this token type + */ + @Override + public String getDescription() { + return description; + } + + /** + * @return whether this token is an end token + */ + public boolean isEndToken() { + return isEndToken; + } + +} diff --git a/languages/scxml/src/main/java/de/jplag/scxml/parser/HandcraftedScxmlTokenGenerator.java b/languages/scxml/src/main/java/de/jplag/scxml/parser/HandcraftedScxmlTokenGenerator.java new file mode 100644 index 000000000..2422e85f2 --- /dev/null +++ b/languages/scxml/src/main/java/de/jplag/scxml/parser/HandcraftedScxmlTokenGenerator.java @@ -0,0 +1,67 @@ +package de.jplag.scxml.parser; + +import static de.jplag.scxml.ScxmlTokenType.*; + +import de.jplag.scxml.parser.model.State; +import de.jplag.scxml.parser.model.Transition; +import de.jplag.scxml.parser.model.executable_content.ExecutableContent; + +/** + * Visits a statechart and its contained elements to extract tokens using a handcrafted strategy, i.e. a larger token + * set than for the simple strategy (see {@link SimpleScxmlTokenGenerator}). Additional tokens are extracted depending + * on the attributes of the statechart elements. + */ +public class HandcraftedScxmlTokenGenerator extends SimpleScxmlTokenGenerator { + + /** + * Creates the token generator. + * @param adapter the parser adapter which receives the generated tokens + */ + public HandcraftedScxmlTokenGenerator(ScxmlParserAdapter adapter) { + super(adapter); + } + + /** + * Visits a state and extracts tokens based on whether its {@code initial} and {@code isRegion} attributes are set to + * {@code true}. + * @param state the state to visit + */ + protected void visitStateAttributes(State state) { + if (state.isRegion() && state.initial()) { + adapter.addToken(INITIAL_REGION, state); + } else if (state.isRegion()) { + adapter.addToken(REGION, state); + } else if (state.initial()) { + adapter.addToken(INITIAL_STATE, state); + } else { + adapter.addToken(STATE, state); + } + } + + @Override + public void visitState(State state) { + visitStateAttributes(state); + depth++; + visitStateContents(state); + depth--; + adapter.addToken(STATE_END, state); + } + + @Override + public void visitTransition(Transition transition) { + if (transition.isTimed()) { + adapter.addToken(TIMED_TRANSITION, transition); + } else if (transition.isGuarded()) { + adapter.addToken(GUARDED_TRANSITION, transition); + } else { + adapter.addToken(TRANSITION, transition); + } + + depth++; + for (ExecutableContent content : transition.contents()) { + visitExecutableContent(content); + } + depth--; + adapter.addToken(TRANSITION_END, transition); + } +} diff --git a/languages/scxml/src/main/java/de/jplag/scxml/parser/PeekAdapter.java b/languages/scxml/src/main/java/de/jplag/scxml/parser/PeekAdapter.java new file mode 100644 index 000000000..87105836d --- /dev/null +++ b/languages/scxml/src/main/java/de/jplag/scxml/parser/PeekAdapter.java @@ -0,0 +1,47 @@ +package de.jplag.scxml.parser; + +import java.util.ArrayList; +import java.util.List; + +import de.jplag.scxml.ScxmlTokenType; +import de.jplag.scxml.parser.model.StatechartElement; + +/** + * A parser adapter that provides a way to retrieve a list of token types. When a token is added, only the ordinal of + * its type is stored. This can be used to "peek" at a list of token types that are extracted when visiting a + * statechart. + */ +public class PeekAdapter extends ScxmlParserAdapter { + + private final List tokenTypes = new ArrayList<>(); + + /** + * Lexicographically compares two lists of integer representations / ordinals of token types. + * @param first the first list of ordinals of token types + * @param second the second list of ordinals of token types + * @return 0 if the lists are equal, a negative integer if the first list is lexicographically less than the second + * list, or a positive integer if the first list is lexicographically greater than the second list + */ + public static int compareTokenTypeLists(List first, List second) { + int size = Math.min(first.size(), second.size()); + for (int i = 0; i < size; i++) { + int result = Integer.compare(first.get(i), second.get(i)); + if (result != 0) { + return result; + } + } + return Integer.compare(first.size(), second.size()); + } + + @Override + public void addToken(ScxmlTokenType type, StatechartElement source) { + tokenTypes.add(type.ordinal()); + } + + /** + * @return the currently extracted list of token types + */ + public List getTokenTypes() { + return tokenTypes; + } +} diff --git a/languages/scxml/src/main/java/de/jplag/scxml/parser/ScxmlParser.java b/languages/scxml/src/main/java/de/jplag/scxml/parser/ScxmlParser.java new file mode 100644 index 000000000..2ca392be0 --- /dev/null +++ b/languages/scxml/src/main/java/de/jplag/scxml/parser/ScxmlParser.java @@ -0,0 +1,139 @@ +package de.jplag.scxml.parser; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.function.Function; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; + +import de.jplag.ParsingException; +import de.jplag.scxml.parser.model.State; +import de.jplag.scxml.parser.model.Statechart; +import de.jplag.scxml.parser.model.Transition; +import de.jplag.scxml.parser.model.executable_content.Action; +import de.jplag.scxml.parser.model.executable_content.ExecutableContent; +import de.jplag.scxml.parser.util.NodeUtil; + +/** + * An SCXML parser implementation based on a Simple API for XML (SAX) parser. Constructs a Statechart object during the + * parse. + */ +public class ScxmlParser { + + private static final String STATE_ELEMENT = "state"; + private static final String PARALLEL_STATE_ELEMENT = "parallel"; + private static final String INITIAL_ELEMENT = "initial"; + private static final String ONENTRY_ELEMENT = "onentry"; + private static final String ONEXIT_ELEMENT = "onexit"; + private static final String TRANSITION_ELEMENT = "transition"; + + private static final String NAME_ATTRIBUTE = "name"; + private static final String ID_ATTRIBUTE = "id"; + private static final String INITIAL_ATTRIBUTE = "initial"; + private static final String TARGET_ATTRIBUTE = "target"; + private static final String EVENT_ATTRIBUTE = "event"; + private static final String CONDITION_ATTRIBUTE = "cond"; + + private final DocumentBuilder builder; + private final List initialStateTargets = new ArrayList<>(); + + /** + * Constructs a new ScxmlParser used to parse SCXML documents. + * @throws ParserConfigurationException when the document builder for parsing the XML files cannot be constructed + */ + public ScxmlParser() throws ParserConfigurationException { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + builder = factory.newDocumentBuilder(); + } + + /** + * Parses the given SCXML file using Javax and constructs a Statechart object. Two passes through the document are + * performed: In the first pass, all {@literal } elements within states are iterated over to resolve initial + * states. In the second pass, the whole document is visited. This is necessary because an initial state may occur in + * the document prior to the transitions pointing to it. + * @param file the SCXML file to parse + * @return the statechart constructed from the input statechart file + * @throws ParsingException when the statechart could not be parsed + */ + public Statechart parse(File file) throws ParsingException { + try { + Document document = builder.parse(file); + Element element = document.getDocumentElement(); + resolveInitialStates(element); + return visitRoot(element); + } catch (SAXException | IOException | IllegalArgumentException e) { + throw new ParsingException(file, "failed to parse statechart: " + e.getMessage()); + } + } + + private void resolveInitialStates(Node root) { + List initialElements = NodeUtil.getNodesRecursive(root, INITIAL_ELEMENT); + List transitions = initialElements.stream().map(this::visitInitialTransition).toList(); + initialStateTargets.addAll(transitions.stream().map(Transition::target).toList()); + } + + private List visitChildElements(Node root, Set childNames, Function visitorFunction) { + return new ArrayList<>(NodeUtil.getChildNodes(root, childNames).stream().map(visitorFunction).toList()); + } + + private Statechart visitRoot(Node node) { + String name = NodeUtil.getAttribute(node, NAME_ATTRIBUTE); + assert name != null : "statechart element must have name attribute"; + + List states = visitChildElements(node, Set.of(STATE_ELEMENT, PARALLEL_STATE_ELEMENT), this::visitState); + return new Statechart(name, states); + } + + private State visitState(Node node) { + String id = NodeUtil.getAttribute(node, ID_ATTRIBUTE); + assert id != null : "state element must have id attribute"; + + boolean initial = initialStateTargets.contains(id) || NodeUtil.getAttribute(node, INITIAL_ATTRIBUTE) != null; + boolean parallel = node.getNodeName().equals(PARALLEL_STATE_ELEMENT); + + Node child = NodeUtil.getFirstChild(node, INITIAL_ELEMENT); + assert !(parallel && child != null) : "parallel state " + id + " must not have initial element"; + + List actions = visitChildElements(node, Set.of(ONENTRY_ELEMENT, ONEXIT_ELEMENT), this::visitAction); + List transitions = visitChildElements(node, Set.of(TRANSITION_ELEMENT), this::visitTransition); + List states = visitChildElements(node, Set.of(STATE_ELEMENT, PARALLEL_STATE_ELEMENT), this::visitState); + return new State(id, transitions, states, actions, initial, parallel); + } + + private Action visitAction(Node node) throws IllegalArgumentException { + if (node == null) { + return null; + } + Action.Type type = node.getNodeName().equals(ONENTRY_ELEMENT) ? Action.Type.ON_ENTRY : Action.Type.ON_EXIT; + return new Action(type, visitExecutableContents(node)); + } + + private List visitExecutableContents(Node node) throws IllegalArgumentException { + return visitChildElements(node, ExecutableContent.ALLOWED_XML_ELEMENTS, ExecutableContent::fromNode); + } + + private Transition visitInitialTransition(Node node) { + List transitionNodes = NodeUtil.getChildNodes(node, TRANSITION_ELEMENT); + assert !transitionNodes.isEmpty() : "initial element must contain transition child"; + Transition transition = visitTransition(transitionNodes.get(0)); + assert transition.isInitial() : "transition is not an initial transition"; + return transition; + } + + private Transition visitTransition(Node node) throws IllegalArgumentException { + return new Transition(NodeUtil.getAttribute(node, TARGET_ATTRIBUTE), NodeUtil.getAttribute(node, EVENT_ATTRIBUTE), + NodeUtil.getAttribute(node, CONDITION_ATTRIBUTE), visitExecutableContents(node), + // Set timed attribute to false initially, may be updated later in the State class + false); + } +} diff --git a/languages/scxml/src/main/java/de/jplag/scxml/parser/ScxmlParserAdapter.java b/languages/scxml/src/main/java/de/jplag/scxml/parser/ScxmlParserAdapter.java new file mode 100644 index 000000000..da8445256 --- /dev/null +++ b/languages/scxml/src/main/java/de/jplag/scxml/parser/ScxmlParserAdapter.java @@ -0,0 +1,103 @@ +package de.jplag.scxml.parser; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import javax.xml.parsers.ParserConfigurationException; + +import de.jplag.AbstractParser; +import de.jplag.ParsingException; +import de.jplag.Token; +import de.jplag.scxml.ScxmlLanguage; +import de.jplag.scxml.ScxmlToken; +import de.jplag.scxml.ScxmlTokenType; +import de.jplag.scxml.parser.model.Statechart; +import de.jplag.scxml.parser.model.StatechartElement; +import de.jplag.scxml.util.AbstractScxmlVisitor; +import de.jplag.scxml.util.ScxmlView; + +/** + * Parser adapter for SCXML statecharts that uses a Statechart object obtained from an instance of ScxmlParser to + * extract tokens. + */ +public class ScxmlParserAdapter extends AbstractParser { + + /** + * The list of extracted tokens for the current file. + */ + protected List tokens; + + /** + * The current statechart input file. + */ + protected File currentStatechartFile; + + /** + * The visitor to use for recursively iterating over the statechart to extract tokens. + */ + protected AbstractScxmlVisitor visitor; + protected ScxmlView view; + + public ScxmlParserAdapter() { + this.visitor = new HandcraftedScxmlTokenGenerator(this); + } + + /** + * Extracts all tokens from a set of files. + * @param files the set of files + * @throws ParsingException if the statechart could not be parsed + * @return the list of parsed tokens + */ + public List parse(Set files) throws ParsingException { + tokens = new ArrayList<>(); + for (File file : files) { + parseStatechartFile(file); + } + return tokens; + } + + /** + * Loads a statechart from a file, parses it and extracts tokens from it. + * @param file the statechart file + * @throws ParsingException if the statechart could not be parsed + */ + protected void parseStatechartFile(File file) throws ParsingException { + currentStatechartFile = file; + Statechart statechart; + view = new ScxmlView(file); + + try { + statechart = new ScxmlParser().parse(file); + } catch (ParserConfigurationException e) { + throw new ParsingException(file, "failed to construct XML document builder:\n" + e.getMessage()); + } + + visitor.visit(statechart); + tokens.add(Token.fileEnd(currentStatechartFile)); + view.writeToFile(ScxmlLanguage.VIEW_FILE_SUFFIX); + } + + /** + * Creates a token from the given type plus the associated statechart element and adds it to the token stream. The token + * is enhanced with view information (see {@link ScxmlView}). + * @param type the type of the token + * @param source the statechart element associated with the token + */ + public void addToken(ScxmlTokenType type, StatechartElement source) { + ScxmlToken token = new ScxmlToken(type, currentStatechartFile, source); + Token enhancedToken = view.enhanceToken(token, visitor.getCurrentStatechartDepth()); + tokens.add(enhancedToken); + } + + /** + * Creates a token from the given type without an associated statechart element. The token is enhanced with view + * information (see {@link ScxmlView}). + * @param type the type of the token + */ + public void addEndToken(ScxmlTokenType type) { + addToken(type, null); + } + +} diff --git a/languages/scxml/src/main/java/de/jplag/scxml/parser/SimpleScxmlTokenGenerator.java b/languages/scxml/src/main/java/de/jplag/scxml/parser/SimpleScxmlTokenGenerator.java new file mode 100644 index 000000000..2954bbf99 --- /dev/null +++ b/languages/scxml/src/main/java/de/jplag/scxml/parser/SimpleScxmlTokenGenerator.java @@ -0,0 +1,167 @@ +package de.jplag.scxml.parser; + +import static de.jplag.scxml.ScxmlTokenType.*; +import static java.util.Map.entry; + +import java.util.List; +import java.util.Map; + +import de.jplag.scxml.ScxmlTokenType; +import de.jplag.scxml.parser.model.State; +import de.jplag.scxml.parser.model.Statechart; +import de.jplag.scxml.parser.model.StatechartElement; +import de.jplag.scxml.parser.model.Transition; +import de.jplag.scxml.parser.model.executable_content.*; +import de.jplag.scxml.util.AbstractScxmlVisitor; + +/** + * Visits a statechart and its contained elements to extract tokens using a simple strategy, i.e. a smaller token set + * than for the handcrafted strategy (see {@link HandcraftedScxmlTokenGenerator}). + */ +public class SimpleScxmlTokenGenerator extends AbstractScxmlVisitor { + + /** + * Creates the token generator. + * @param adapter the parser adapter which receives the generated tokens + */ + public SimpleScxmlTokenGenerator(ScxmlParserAdapter adapter) { + super(adapter); + } + + @Override + public void visitStatechart(Statechart statechart) { + depth = 0; + for (State state : sorter.sort(statechart.states())) { + visitState(state); + } + } + + /** + * Visits the actions, transitions and substates of a state. Either of these attributes may be an empty list in which + * case no tokens are extracted. + * @param state the state whose actions, transitions and substates to visit + */ + protected void visitStateContents(State state) { + visitActions(state.actions()); + for (Transition transition : sorter.sort(state.transitions())) { + visitTransition(transition); + } + for (State substate : sorter.sort(state.substates())) { + visitState(substate); + } + } + + @Override + public void visitState(State state) { + adapter.addToken(STATE, state); + depth++; + visitStateContents(state); + depth--; + adapter.addEndToken(STATE_END); + } + + @Override + public void visitActions(List actions) { + // Group actions by their type + List onEntries = actions.stream().filter(a -> a.type() == Action.Type.ON_ENTRY).toList(); + List onExits = actions.stream().filter(a -> a.type() == Action.Type.ON_EXIT).toList(); + visitActions(onEntries, ON_ENTRY); + visitActions(onExits, ON_EXIT); + } + + private void visitActions(List actions, ScxmlTokenType tokenType) { + if (!actions.isEmpty()) { + // Only extract a single ENTRY / EXIT token even if the state contains multiple. + // Functionally, this makes no difference. + adapter.addToken(tokenType, actions.get(0)); + List actionContents = actions.stream().flatMap(a -> a.contents().stream()).toList(); + depth++; + // Do not sort executable content because the order is important + for (ExecutableContent content : actionContents) { + visitExecutableContent(content); + } + depth--; + adapter.addEndToken(ACTION_END); + } + } + + @Override + public void visitTransition(Transition transition) { + adapter.addToken(TRANSITION, transition); + depth++; + // Do not sort executable content because the order is important + for (ExecutableContent content : transition.contents()) { + visitExecutableContent(content); + } + depth--; + adapter.addEndToken(TRANSITION_END); + } + + @Override + public void visitIf(If ifElement) { + adapter.addToken(IF, ifElement); + depth++; + for (ExecutableContent content : ifElement.contents()) { + visitExecutableContent(content); + } + for (ElseIf elseIf : ifElement.elseIfs()) { + visitElseIf(elseIf); + } + visitElse(ifElement.else_()); + depth--; + adapter.addEndToken(IF_END); + } + + @Override + public void visitElseIf(ElseIf elseIf) { + adapter.addToken(ELSE_IF, elseIf); + for (ExecutableContent content : elseIf.contents()) { + visitExecutableContent(content); + } + adapter.addEndToken(ELSE_IF_END); + } + + @Override + public void visitElse(Else elseElement) { + if (elseElement != null) { + adapter.addToken(ELSE, elseElement); + for (ExecutableContent content : elseElement.contents()) { + visitExecutableContent(content); + } + adapter.addToken(ELSE_END, elseElement); + } + } + + @Override + public void visitExecutableContent(ExecutableContent content) { + if (content instanceof SimpleExecutableContent simpleExecutableContent) { + visitSimpleExecutableContent(simpleExecutableContent); + return; + } + + if (content instanceof If visitElement) { + visitIf(visitElement); + return; + } + + Map, ScxmlTokenType> tokenTypeMap = Map.ofEntries(entry(Send.class, SEND), entry(Cancel.class, CANCEL)); + ScxmlTokenType type = tokenTypeMap.get(content.getClass()); + adapter.addToken(type, content); + } + + @Override + public void visitSimpleExecutableContent(SimpleExecutableContent content) { + ScxmlTokenType type = switch (content.type()) { + case RAISE -> RAISE; + case ASSIGNMENT -> ASSIGNMENT; + case SCRIPT -> SCRIPT; + case FOREACH -> FOREACH; + // Don't extract a token for log elements + case LOG -> null; + }; + if (type != null) { + adapter.addToken(type, content); + } + } + +} diff --git a/languages/scxml/src/main/java/de/jplag/scxml/parser/model/State.java b/languages/scxml/src/main/java/de/jplag/scxml/parser/model/State.java new file mode 100644 index 000000000..b7d8737f9 --- /dev/null +++ b/languages/scxml/src/main/java/de/jplag/scxml/parser/model/State.java @@ -0,0 +1,159 @@ +package de.jplag.scxml.parser.model; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Stream; + +import de.jplag.scxml.parser.model.executable_content.Action; +import de.jplag.scxml.parser.model.executable_content.Cancel; +import de.jplag.scxml.parser.model.executable_content.ExecutableContent; +import de.jplag.scxml.parser.model.executable_content.Send; + +/** + * Represents an SCXML {@code } element in the statechart model. A state can be a simple state, an initial state, + * a parallel state, or a region (a state containing substates). A state can have outgoing transitions, actions (such as + * onentry and onexit), and timed transitions (a concept specific to itemis CREATE). + * @param id the ID of the state + * @param transitions a non-null list of outgoing transitions of this state + * @param substates a non-null list of substates of this state + * @param actions a non-null list of actions associated with this state + * @param initial whether this state is an initial state + * @param parallel whether this state is a parallel state + */ +public record State(String id, List transitions, List substates, List actions, boolean initial, boolean parallel) + implements StatechartElement { + + /** + * Constructs a new state. + * @throws IllegalArgumentException if {@code transitions} or {@code substates} is null + */ + public State(String id, List transitions, List substates, List actions, boolean initial, boolean parallel) { + if (transitions == null) { + throw new IllegalArgumentException("State.transitions must not be null"); + } + + if (substates == null) { + throw new IllegalArgumentException("State.substates must not be null"); + } + + this.id = id; + this.transitions = transitions; + this.substates = substates; + this.actions = actions; + this.initial = initial; + this.parallel = parallel; + updateTimedTransitions(); + } + + /** + * Constructs a state with an ID, setting all other variables to default values. + * @param id the ID of the state + */ + public State(String id) { + this(id, new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), false, false); + } + + /** + * @return whether this state is a region, i.e. it contains at least one substate + */ + public boolean isRegion() { + return !substates.isEmpty(); + } + + /** + * @return whether this state is a simple state, meaning that is neither an initial state nor a parallel state + */ + public boolean isSimple() { + return !initial && !parallel; + } + + private Stream onEntries() { + return actions.stream().filter(a -> a.type() == Action.Type.ON_ENTRY); + } + + private Stream onExits() { + return actions.stream().filter(a -> a.type() == Action.Type.ON_EXIT); + } + + private List getOnEntrySends() { + Stream> onEntryContents = this.onEntries().map(Action::contents); + return onEntryContents.flatMap(List::stream).filter(Send.class::isInstance).map(s -> (Send) s).toList(); + } + + /** + * Sets the timed attribute of each transition of this state that is timed. To model a timed transition, itemis Create + * adds onentry.send, onexit.cancel and transition elements with matching IDs. These elements will be removed if they + * are part of a timed transition. + **/ + private void updateTimedTransitions() { + if (this.transitions().isEmpty() || this.actions().isEmpty()) { + return; + } + + for (Action onExit : onExits().toList()) { + var cancelElements = onExit.contents().stream().filter(Cancel.class::isInstance).map(c -> (Cancel) c).toList(); + for (Cancel cancel : cancelElements) { + replaceMatchingTransitions(cancel.sendid(), onExit, cancel); + } + } + } + + private void replaceMatchingTransitions(String sendId, Action onExit, Cancel cancel) { + List onEntrySends = getOnEntrySends(); + for (Transition transition : transitions) { + boolean foundTimedTransition = false; + // Then check if there is also a matching send element in + if (isMatchingTransition(transition, sendId) && onEntries().toList().stream().anyMatch(onEntry -> { + Optional matchingSend = onEntrySends.stream().filter(send -> send.event().equals(sendId)).map(send -> { + removeTimedTransitionElements(onEntry, send, onExit, cancel); + return send; + }).findFirst(); + return matchingSend.isPresent(); + })) { + foundTimedTransition = true; + } + if (foundTimedTransition) { + // Replace the transition with a timed transition + transitions.set(transitions.indexOf(transition), Transition.makeTimed(transition)); + } + } + } + + private boolean isMatchingTransition(Transition transition, String sendId) { + return transition.event() != null && transition.event().equals(sendId); + } + + private void removeTimedTransitionElements(Action onEntry, Send send, Action onExit, Cancel cancel) { + List filteredContents = onEntry.contents().stream().filter(c -> !(c instanceof Send && c.equals(send))).toList(); + if (filteredContents.isEmpty()) { + // Remove onEntry entirely if it is now empty + actions.remove(onEntry); + } else { + // Only remove the matching onEntry.send + Action filteredOnEntry = new Action(Action.Type.ON_ENTRY, filteredContents); + actions.set(actions.indexOf(onEntry), filteredOnEntry); + } + + // Do something similar for onExit + filteredContents = onExit.contents().stream().filter(c -> !(c instanceof Cancel && c.equals(cancel))).toList(); + if (filteredContents.isEmpty()) { + actions.remove(onExit); + } else { + Action filteredOnExit = new Action(Action.Type.ON_EXIT, filteredContents); + actions.set(actions.indexOf(onExit), filteredOnExit); + } + } + + @Override + public String toString() { + String[] parts = {"", ""}; + parts[1] = isRegion() ? "Region" : "State"; + if (initial) { + parts[0] = "Initial "; + parts[1] = parts[1].toLowerCase(); + } + return String.format("%s: %s%s {", id, parts[0], parts[1]); + } + +} diff --git a/languages/scxml/src/main/java/de/jplag/scxml/parser/model/Statechart.java b/languages/scxml/src/main/java/de/jplag/scxml/parser/model/Statechart.java new file mode 100644 index 000000000..738f3e974 --- /dev/null +++ b/languages/scxml/src/main/java/de/jplag/scxml/parser/model/Statechart.java @@ -0,0 +1,16 @@ +package de.jplag.scxml.parser.model; + +import java.util.List; + +/** + * Represents an SCXML statechart. + * @param name the name of the statechart + * @param states a list of states comprising this statechart + */ +public record Statechart(String name, List states) implements StatechartElement { + + @Override + public String toString() { + return "%s: Statechart {"; + } +} diff --git a/languages/scxml/src/main/java/de/jplag/scxml/parser/model/StatechartElement.java b/languages/scxml/src/main/java/de/jplag/scxml/parser/model/StatechartElement.java new file mode 100644 index 000000000..9696edd07 --- /dev/null +++ b/languages/scxml/src/main/java/de/jplag/scxml/parser/model/StatechartElement.java @@ -0,0 +1,8 @@ +package de.jplag.scxml.parser.model; + +/** + * Defines a common supertype of all elements in an SCXML statechart. This is used to be able to handle any concrete + * statechart element. + */ +public interface StatechartElement { +} diff --git a/languages/scxml/src/main/java/de/jplag/scxml/parser/model/Transition.java b/languages/scxml/src/main/java/de/jplag/scxml/parser/model/Transition.java new file mode 100644 index 000000000..b2a2651b4 --- /dev/null +++ b/languages/scxml/src/main/java/de/jplag/scxml/parser/model/Transition.java @@ -0,0 +1,74 @@ +package de.jplag.scxml.parser.model; + +import java.util.List; +import java.util.Objects; + +import de.jplag.scxml.parser.model.executable_content.ExecutableContent; + +/** + * Represents an SCXML {@literal } element. A transition defines the behavior of a statechart when a + * specific event occurs or when a condition is met. + * @param target the ID of the target state + * @param event the value of the {@literal } attribute of this transition + * @param cond the cond attribute of the {@literal } element which is the condition expression for the transition to + * be executed + * @param contents the list of executable contents to be executed when the transition is performed + * @param timed whether this transition is timed (not part of standard SCXML, but can be modelled by using + * {@literal }, {@literal } and {@literal } elements) + */ +public record Transition(String target, String event, String cond, List contents, boolean timed) implements StatechartElement { + + /** + * Creates a new timed transition based on the given transition. + * @param transition the original transition + * @return a new transition with the timed flag set to true + */ + public static Transition makeTimed(Transition transition) { + return new Transition(transition.target, null, transition.cond, transition.contents, true); + } + + /** + * Checks if the transition is an initial transition. + * @return whether the transition is initial + */ + public boolean isInitial() { + return target != null && event == null && cond == null; + } + + /** + * Checks if the transition is guarded. + * @return whether the condition is not null + */ + public boolean isGuarded() { + return cond != null; + } + + /** + * Checks if the transition is timed. + * @return whether the transition is timed + */ + public boolean isTimed() { + return timed; + } + + @Override + public String toString() { + String prefix = isTimed() ? "Timed t" : "T"; + String suffix; + if (event == null && cond == null) { + suffix = ""; + } else if (event != null && cond != null) { + suffix = String.format("(event='%s', cond='%s')", event, cond); + } else if (event != null) { + suffix = String.format("(event='%s')", event); + } else { + suffix = String.format("(cond='%s')", cond); + } + return String.format("%sransition (-> %s) %s {", prefix, target, suffix); + } + + @Override + public int hashCode() { + return Objects.hash(target, event, cond, contents, timed); + } +} diff --git a/languages/scxml/src/main/java/de/jplag/scxml/parser/model/executable_content/Action.java b/languages/scxml/src/main/java/de/jplag/scxml/parser/model/executable_content/Action.java new file mode 100644 index 000000000..b3a796db5 --- /dev/null +++ b/languages/scxml/src/main/java/de/jplag/scxml/parser/model/executable_content/Action.java @@ -0,0 +1,37 @@ +package de.jplag.scxml.parser.model.executable_content; + +import java.util.List; +import java.util.Objects; + +/** + * Represents {@literal } and {@literal } SCXML elements which contain executable content to be + * executed when a state is entered / exited. + * @param type the type of the action ({@link Type#ON_ENTRY} or {@link Type#ON_EXIT}) + * @param contents the list of executable contents within the action + */ +public record Action(Type type, List contents) implements ExecutableContent { + + @Override + public int hashCode() { + return Objects.hash(type, contents); + } + + @Override + public String toString() { + return String.format("%s {", type == Type.ON_ENTRY ? "OnEntry" : "OnExit"); + } + + /** + * The type of the action. + */ + public enum Type { + /** + * Represents an {@literal } SCXML element. + */ + ON_ENTRY, + /** + * Represents an {@literal } SCXML element. + */ + ON_EXIT, + } +} diff --git a/languages/scxml/src/main/java/de/jplag/scxml/parser/model/executable_content/Cancel.java b/languages/scxml/src/main/java/de/jplag/scxml/parser/model/executable_content/Cancel.java new file mode 100644 index 000000000..b0f5a63ba --- /dev/null +++ b/languages/scxml/src/main/java/de/jplag/scxml/parser/model/executable_content/Cancel.java @@ -0,0 +1,13 @@ +package de.jplag.scxml.parser.model.executable_content; + +/** + * Represents a {@literal } SCXML element. + * @param sendid represents the sendid attribute of the SCXML element which is the ID of the event to be cancelled + */ +public record Cancel(String sendid) implements ExecutableContent { + + @Override + public String toString() { + return "Cancel"; + } +} diff --git a/languages/scxml/src/main/java/de/jplag/scxml/parser/model/executable_content/Else.java b/languages/scxml/src/main/java/de/jplag/scxml/parser/model/executable_content/Else.java new file mode 100644 index 000000000..9c7602af1 --- /dev/null +++ b/languages/scxml/src/main/java/de/jplag/scxml/parser/model/executable_content/Else.java @@ -0,0 +1,16 @@ +package de.jplag.scxml.parser.model.executable_content; + +import java.util.List; + +/** + * Represents an {@literal } SCXML element, which is part of an {@link If} element used when all the preceding + * conditions in the {@literal } and {@literal } elements are not met. + * @param contents the list of executable content to be executed when the {@literal } branch is reached + */ +public record Else(List contents) implements ExecutableContent { + + @Override + public String toString() { + return "Else {"; + } +} diff --git a/languages/scxml/src/main/java/de/jplag/scxml/parser/model/executable_content/ElseIf.java b/languages/scxml/src/main/java/de/jplag/scxml/parser/model/executable_content/ElseIf.java new file mode 100644 index 000000000..8346ab651 --- /dev/null +++ b/languages/scxml/src/main/java/de/jplag/scxml/parser/model/executable_content/ElseIf.java @@ -0,0 +1,17 @@ +package de.jplag.scxml.parser.model.executable_content; + +import java.util.List; + +/** + * Represents an {@literal } SCXML element, which is part of an {@link If} element used for handling multiple + * conditions. The {@literal } element is executed when the preceding {@literal } condition and any prior + * {@literal } conditions are not met and its own condition is satisfied. + * @param contents the list of executable content to be executed when the {@literal } branch is reached + */ +public record ElseIf(List contents) implements ExecutableContent { + + @Override + public String toString() { + return "ElseIf {"; + } +} diff --git a/languages/scxml/src/main/java/de/jplag/scxml/parser/model/executable_content/ExecutableContent.java b/languages/scxml/src/main/java/de/jplag/scxml/parser/model/executable_content/ExecutableContent.java new file mode 100644 index 000000000..17d4ee1e6 --- /dev/null +++ b/languages/scxml/src/main/java/de/jplag/scxml/parser/model/executable_content/ExecutableContent.java @@ -0,0 +1,110 @@ +package de.jplag.scxml.parser.model.executable_content; + +import static de.jplag.scxml.parser.model.executable_content.SimpleExecutableContent.Type.*; + +import java.util.Set; + +import org.w3c.dom.Node; + +import de.jplag.scxml.parser.model.StatechartElement; +import de.jplag.scxml.parser.util.NodeUtil; + +/** + * Represents executable content in an SCXML statechart, which are elements that can be executed during state + * transitions, state entry, state exit or in conditional statements. + */ +public interface ExecutableContent extends StatechartElement { + + /** + * String constant for the "event" attribute. + */ + String EVENT_ATTRIBUTE = "event"; + + /** + * String constant for the "sendid" attribute. + */ + String SEND_ID_ATTRIBUTE = "sendid"; + + /** + * String constant for the "delay" attribute. + */ + String DELAY_ATTRIBUTE = "delay"; + + /** + * String constant for the {@literal } element. + */ + String RAISE_ELEMENT = "raise"; + + /** + * String constant for the {@literal } element. + */ + String IF_ELEMENT = "if"; + + /** + * String constant for the {@literal } element. + */ + String FOREACH_ELEMENT = "foreach"; + + /** + * String constant for the {@literal } element. + */ + String LOG_ELEMENT = "log"; + + /** + * String constant for the {@literal } element. + */ + String ASSIGN_ELEMENT = "assign"; + + /** + * String constant for the {@literal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/languages/scxml/src/test/resources/de/jplag/statecharts/simple.scxml b/languages/scxml/src/test/resources/de/jplag/statecharts/simple.scxml new file mode 100644 index 000000000..895c56c58 --- /dev/null +++ b/languages/scxml/src/test/resources/de/jplag/statecharts/simple.scxml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/languages/scxml/src/test/resources/de/jplag/statecharts/timed_transition.scxml b/languages/scxml/src/test/resources/de/jplag/statecharts/timed_transition.scxml new file mode 100644 index 000000000..da609a5ff --- /dev/null +++ b/languages/scxml/src/test/resources/de/jplag/statecharts/timed_transition.scxml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/languages/swift/README.md b/languages/swift/README.md index 9d0031fdb..5e9c94e27 100644 --- a/languages/swift/README.md +++ b/languages/swift/README.md @@ -16,7 +16,7 @@ The choice of tokens is intended to be similar to the Java or C# frontends. It i ### Usage -To use the Swift frontend, add the `-l swift` flag in the CLI, or use a `JPlagOption` object with `new de.jplag.swift.Language()` as `language` in the Java API as described in the usage information in the [readme of the main project](https://github.com/jplag/JPlag#usage) and [in the wiki](https://github.com/jplag/JPlag/wiki/1.-How-to-Use-JPlag). +To use the Swift frontend, add the `-l swift` flag in the CLI, or use a `JPlagOption` object with `new de.jplag.swift.SwiftLanguage()` as `language` in the Java API as described in the usage information in the [readme of the main project](https://github.com/jplag/JPlag#usage) and [in the wiki](https://github.com/jplag/JPlag/wiki/1.-How-to-Use-JPlag).
diff --git a/languages/swift/src/main/java/de/jplag/swift/Language.java b/languages/swift/src/main/java/de/jplag/swift/SwiftLanguage.java similarity index 92% rename from languages/swift/src/main/java/de/jplag/swift/Language.java rename to languages/swift/src/main/java/de/jplag/swift/SwiftLanguage.java index 19c7426e5..b02aa9094 100644 --- a/languages/swift/src/main/java/de/jplag/swift/Language.java +++ b/languages/swift/src/main/java/de/jplag/swift/SwiftLanguage.java @@ -13,7 +13,7 @@ * This represents the Swift language as a language supported by JPlag. */ @MetaInfServices(de.jplag.Language.class) -public class Language implements de.jplag.Language { +public class SwiftLanguage implements de.jplag.Language { private static final String IDENTIFIER = "swift"; @@ -22,7 +22,7 @@ public class Language implements de.jplag.Language { private static final String[] FILE_EXTENSIONS = {".swift"}; private final SwiftParserAdapter parserAdapter; - public Language() { + public SwiftLanguage() { this.parserAdapter = new SwiftParserAdapter(); } diff --git a/languages/swift/src/main/java/de/jplag/swift/SwiftParserAdapter.java b/languages/swift/src/main/java/de/jplag/swift/SwiftParserAdapter.java index a6614257f..26c8025a8 100644 --- a/languages/swift/src/main/java/de/jplag/swift/SwiftParserAdapter.java +++ b/languages/swift/src/main/java/de/jplag/swift/SwiftParserAdapter.java @@ -1,7 +1,7 @@ package de.jplag.swift; +import java.io.BufferedReader; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -18,6 +18,7 @@ import de.jplag.Token; import de.jplag.swift.grammar.Swift5Lexer; import de.jplag.swift.grammar.Swift5Parser; +import de.jplag.util.FileUtils; public class SwiftParserAdapter extends AbstractParser { @@ -47,10 +48,10 @@ public List parse(Set files) throws ParsingException { } private void parse(File file) throws ParsingException { - try (FileInputStream inputStream = new FileInputStream(file)) { + try (BufferedReader reader = FileUtils.openFileReader(file)) { currentFile = file; - Swift5Lexer lexer = new Swift5Lexer(CharStreams.fromStream(inputStream)); + Swift5Lexer lexer = new Swift5Lexer(CharStreams.fromReader(reader)); CommonTokenStream tokenStream = new CommonTokenStream(lexer); Swift5Parser parser = new Swift5Parser(tokenStream); diff --git a/languages/swift/src/main/java/de/jplag/swift/SwiftTokenType.java b/languages/swift/src/main/java/de/jplag/swift/SwiftTokenType.java index 3b69cb6eb..0bfc07640 100644 --- a/languages/swift/src/main/java/de/jplag/swift/SwiftTokenType.java +++ b/languages/swift/src/main/java/de/jplag/swift/SwiftTokenType.java @@ -53,6 +53,7 @@ public enum SwiftTokenType implements TokenType { private final String description; + @Override public String getDescription() { return description; } diff --git a/languages/swift/src/test/java/de/jplag/swift/SwiftFrontendTest.java b/languages/swift/src/test/java/de/jplag/swift/SwiftFrontendTest.java index 705843eb0..d6f3469d9 100644 --- a/languages/swift/src/test/java/de/jplag/swift/SwiftFrontendTest.java +++ b/languages/swift/src/test/java/de/jplag/swift/SwiftFrontendTest.java @@ -55,11 +55,11 @@ class SwiftFrontendTest { private final Logger logger = LoggerFactory.getLogger(SwiftFrontendTest.class); private final String[] testFiles = new String[] {COMPLETE_TEST_FILE}; private final File testFileLocation = Path.of("src", "test", "resources", "de", "jplag", "swift").toFile(); - private Language language; + private SwiftLanguage language; @BeforeEach void setup() { - language = new Language(); + language = new SwiftLanguage(); } @Test diff --git a/languages/text/src/main/java/de/jplag/text/Language.java b/languages/text/src/main/java/de/jplag/text/NaturalLanguage.java similarity index 93% rename from languages/text/src/main/java/de/jplag/text/Language.java rename to languages/text/src/main/java/de/jplag/text/NaturalLanguage.java index 03693ba0e..a9b974840 100644 --- a/languages/text/src/main/java/de/jplag/text/Language.java +++ b/languages/text/src/main/java/de/jplag/text/NaturalLanguage.java @@ -15,12 +15,12 @@ * but there are better approaches for text plagiarism out there (based on NLP techniques). */ @MetaInfServices(de.jplag.Language.class) -public class Language implements de.jplag.Language { +public class NaturalLanguage implements de.jplag.Language { private static final String IDENTIFIER = "text"; private final ParserAdapter parserAdapter; - public Language() { + public NaturalLanguage() { parserAdapter = new ParserAdapter(); } diff --git a/languages/text/src/main/java/de/jplag/text/ParserAdapter.java b/languages/text/src/main/java/de/jplag/text/ParserAdapter.java index 975dbe7e3..c3d1ccc83 100644 --- a/languages/text/src/main/java/de/jplag/text/ParserAdapter.java +++ b/languages/text/src/main/java/de/jplag/text/ParserAdapter.java @@ -2,7 +2,6 @@ import java.io.File; import java.io.IOException; -import java.nio.file.Files; import java.util.ArrayList; import java.util.List; import java.util.Properties; @@ -11,6 +10,7 @@ import de.jplag.AbstractParser; import de.jplag.ParsingException; import de.jplag.Token; +import de.jplag.util.FileUtils; import edu.stanford.nlp.ling.CoreLabel; import edu.stanford.nlp.pipeline.CoreDocument; @@ -100,7 +100,7 @@ private void addToken(CoreLabel label) { private String readFile(File file) throws ParsingException { try { - return Files.readString(file.toPath()); + return FileUtils.readFileContent(file); } catch (IOException e) { throw new ParsingException(file, e.getMessage(), e); } diff --git a/languages/text/src/main/java/de/jplag/text/TextTokenType.java b/languages/text/src/main/java/de/jplag/text/TextTokenType.java index 1fc2277d9..23b3ce893 100644 --- a/languages/text/src/main/java/de/jplag/text/TextTokenType.java +++ b/languages/text/src/main/java/de/jplag/text/TextTokenType.java @@ -7,6 +7,7 @@ public TextTokenType(String description) { this.description = description.toLowerCase(); } + @Override public String getDescription() { return this.description; } diff --git a/languages/text/src/test/java/jplag/text/TextLanguageTest.java b/languages/text/src/test/java/jplag/text/NaturalLanguageTest.java similarity index 69% rename from languages/text/src/test/java/jplag/text/TextLanguageTest.java rename to languages/text/src/test/java/jplag/text/NaturalLanguageTest.java index 09fe29b4c..9e16e4532 100644 --- a/languages/text/src/test/java/jplag/text/TextLanguageTest.java +++ b/languages/text/src/test/java/jplag/text/NaturalLanguageTest.java @@ -13,7 +13,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.slf4j.Logger; @@ -23,10 +22,10 @@ import de.jplag.Token; import de.jplag.TokenPrinter; import de.jplag.TokenType; -import de.jplag.text.Language; +import de.jplag.text.NaturalLanguage; -class TextLanguageTest { - private final Logger logger = LoggerFactory.getLogger(TextLanguageTest.class); +class NaturalLanguageTest { + private final Logger logger = LoggerFactory.getLogger(NaturalLanguageTest.class); private static final Path BASE_PATH = Path.of("src", "test", "resources"); private static final String TEST_SUBJECT = "FutureJavaDoc.txt"; @@ -36,7 +35,7 @@ class TextLanguageTest { @BeforeEach public void setUp() { - language = new Language(); + language = new NaturalLanguage(); baseDirectory = BASE_PATH.toFile(); assertTrue(baseDirectory.exists(), "Could not find base directory!"); } @@ -54,19 +53,19 @@ void testParsingJavaDoc() throws ParsingException { @ParameterizedTest @ValueSource(strings = {"\n", "\r", "\r\n",}) - void testLineBreakInputs(String input, @TempDir Path tempDir) throws IOException, ParsingException { - Path filePath = tempDir.resolve("input.txt"); - Files.writeString(filePath, input); - List result = language.parse(Set.of(filePath.toFile())); + void testLineBreakInputs(String input) throws IOException, ParsingException { + File testFile = File.createTempFile("input", "txt"); + Files.writeString(testFile.toPath(), input); + List result = language.parse(Set.of(testFile)); assertEquals(1, result.size()); } @ParameterizedTest @ValueSource(strings = {"\ntoken", "\rtoken", "\r\ntoken",}) - void testTokenAfterLineBreak(String input, @TempDir Path tempDir) throws IOException, ParsingException { - Path filePath = tempDir.resolve("input.txt"); - Files.writeString(filePath, input); - List result = language.parse(Set.of(filePath.toFile())); + void testTokenAfterLineBreak(String input) throws IOException, ParsingException { + File testFile = File.createTempFile("input", "txt"); + Files.writeString(testFile.toPath(), input); + List result = language.parse(Set.of(testFile)); assertEquals(2, result.get(0).getLine()); } diff --git a/languages/typescript/README.md b/languages/typescript/README.md new file mode 100644 index 000000000..351bc2da2 --- /dev/null +++ b/languages/typescript/README.md @@ -0,0 +1,24 @@ +# JPlag TypeScript language module +Due to TypeScript being a superset of JavaScript this frontend can also parse JavaScript files. +
+The JPlag TypeScript module allows the use of JPlag with submissions in TypeScript.
+It is based on the [TypeScript ANTLR4 grammar](https://github.com/antlr/grammars-v4/tree/master/javascript/typescript), licensed under the Apache 2.0. + + +### TypeScript specification compatibility +> This TypeScript grammar does not exactly correspond to the TypeScript standard. The main goal during developing was practical usage, performance, and clarity (getting rid of duplicates). + +Since the grammar has no support for decorators the version can be estimated < 5.0. The grammar can still parse files with decorators, but can not extract a tokens for them. +
The grammar can parse multiple language features from version 4.x. +
Because of this the version is still given as an estimated v5. + +If there are any major updates or fixes to the grammar1, they should surely be applied to this module as well. + +### Token Extraction +The choice of tokens is intended to be similar to the Java or Python modules. It includes a range of nesting structures (class, method, control flow expressions) as well as variable declaration, object creation and assignment. + +### Usage +To use the TypeScript module, use the `typescript` subcommand in the CLI, or use a `JPlagOption` object with `new de.jplag.typescript.TypeScriptLanguage()` as `language` in the Java API as described in the usage information in the [readme of the main project](https://github.com/jplag/JPlag#usage) and [in the wiki](https://github.com/jplag/JPlag/wiki/1.-How-to-Use-JPlag). + +#### Footnotes +

1 The grammar files are taken from grammar-v4, with the most recent modification in commit 768b12e from March 2023.
\ No newline at end of file diff --git a/languages/typescript/pom.xml b/languages/typescript/pom.xml new file mode 100644 index 000000000..f866687aa --- /dev/null +++ b/languages/typescript/pom.xml @@ -0,0 +1,40 @@ + + + 4.0.0 + + + de.jplag + languages + ${revision} + + typescript + + + + org.antlr + antlr4-runtime + + + de.jplag + language-antlr-utils + ${revision} + compile + + + + + + + org.antlr + antlr4-maven-plugin + + + + antlr4 + + + + + + + diff --git a/languages/typescript/src/main/antlr4/de/jplag/typescript/grammar/TypeScriptLexer.g4 b/languages/typescript/src/main/antlr4/de/jplag/typescript/grammar/TypeScriptLexer.g4 new file mode 100644 index 000000000..3f2d34d80 --- /dev/null +++ b/languages/typescript/src/main/antlr4/de/jplag/typescript/grammar/TypeScriptLexer.g4 @@ -0,0 +1,309 @@ +/// This grammer was slightly modified, so the generated code fit the JPlag code style +lexer grammar TypeScriptLexer; + +channels { ERROR } + +options { + superClass=TypeScriptLexerBase; +} + + +MultiLineComment: '/*' .*? '*/' -> channel(HIDDEN); +SingleLineComment: '//' ~[\r\n\u2028\u2029]* -> channel(HIDDEN); +RegularExpressionLiteral: '/' RegularExpressionFirstChar RegularExpressionChar* {this.isRegexPossible()}? '/' IdentifierPart*; + +OpenBracket: '['; +CloseBracket: ']'; +OpenParen: '('; +CloseParen: ')'; +OpenBrace: '{' {this.processOpenBrace();}; +TemplateCloseBrace: {this.isInTemplateString()}? '}' -> popMode; +CloseBrace: '}' {this.processCloseBrace();}; +SemiColon: ';'; +Comma: ','; +Assign: '='; +QuestionMark: '?'; +Colon: ':'; +Ellipsis: '...'; +Dot: '.'; +PlusPlus: '++'; +MinusMinus: '--'; +Plus: '+'; +Minus: '-'; +BitNot: '~'; +Not: '!'; +Multiply: '*'; +Divide: '/'; +Modulus: '%'; +RightShiftArithmetic: '>>'; +LeftShiftArithmetic: '<<'; +RightShiftLogical: '>>>'; +LessThan: '<'; +MoreThan: '>'; +LessThanEquals: '<='; +GreaterThanEquals: '>='; +Equals_: '=='; +NotEquals: '!='; +IdentityEquals: '==='; +IdentityNotEquals: '!=='; +BitAnd: '&'; +BitXOr: '^'; +BitOr: '|'; +And: '&&'; +Or: '||'; +MultiplyAssign: '*='; +DivideAssign: '/='; +ModulusAssign: '%='; +PlusAssign: '+='; +MinusAssign: '-='; +LeftShiftArithmeticAssign: '<<='; +RightShiftArithmeticAssign: '>>='; +RightShiftLogicalAssign: '>>>='; +BitAndAssign: '&='; +BitXorAssign: '^='; +BitOrAssign: '|='; +ARROW: '=>'; + +/// Null Literals + +NullLiteral: 'null'; + +/// Boolean Literals + +BooleanLiteral: 'true' + | 'false'; + +/// Numeric Literals + +DecimalLiteral: DecimalIntegerLiteral '.' [0-9]* ExponentPart? + | '.' [0-9]+ ExponentPart? + | DecimalIntegerLiteral ExponentPart? + ; + +/// Numeric Literals + +HexIntegerLiteral: '0' [xX] HexDigit+; +OctalIntegerLiteral: '0' [0-7]+ {!this.isStrictMode()}?; +OctalIntegerLiteral2: '0' [oO] [0-7]+; +BinaryIntegerLiteral: '0' [bB] [01]+; + +/// Keywords + +Break: 'break'; +Do: 'do'; +Instanceof: 'instanceof'; +Typeof: 'typeof'; +Case: 'case'; +Else: 'else'; +New: 'new'; +Var: 'var'; +Catch: 'catch'; +Finally: 'finally'; +Return: 'return'; +Void: 'void'; +Continue: 'continue'; +For: 'for'; +Switch: 'switch'; +While: 'while'; +Debugger: 'debugger'; +Function_: 'function'; +This: 'this'; +With: 'with'; +Default: 'default'; +If: 'if'; +Throw: 'throw'; +Delete: 'delete'; +In: 'in'; +Try: 'try'; +As: 'as'; +From: 'from'; +ReadOnly: 'readonly'; +Async: 'async'; + +/// Future Reserved Words + +Class: 'class'; +Enum: 'enum'; +Extends: 'extends'; +Super: 'super'; +Const: 'const'; +Export: 'export'; +Import: 'import'; + +/// The following tokens are also considered to be FutureReservedWords +/// when parsing strict mode + +Implements: 'implements' ; +Let: 'let' ; +Private: 'private' ; +Public: 'public' ; +Interface: 'interface' ; +Package: 'package' ; +Protected: 'protected' ; +Static: 'static' ; +Yield: 'yield' ; + +//keywords: + +Any : 'any'; +Number: 'number'; +Boolean: 'boolean'; +String: 'string'; +Symbol: 'symbol'; + + +TypeAlias : 'type'; + +Get: 'get'; +Set: 'set'; + +Constructor: 'constructor'; +Namespace: 'namespace'; +Require: 'require'; +Module: 'module'; +Declare: 'declare'; + +Abstract: 'abstract'; + +Is: 'is'; + +// +// Ext.2 Additions to 1.8: Decorators +// +At: '@'; + +/// Identifier Names and Identifiers + +Identifier: IdentifierStart IdentifierPart*; + +/// String Literals +StringLiteral: ('"' DoubleStringCharacter* '"' + | '\'' SingleStringCharacter* '\'') {this.processStringLiteral();} + ; + +BackTick: '`' {this.increaseTemplateDepth();} -> pushMode(TEMPLATE); + +WhiteSpaces: [\t\u000B\u000C\u0020\u00A0]+ -> channel(HIDDEN); + +LineTerminator: [\r\n\u2028\u2029] -> channel(HIDDEN); + +/// Comments + + +HtmlComment: '' -> channel(HIDDEN); +CDataComment: '' -> channel(HIDDEN); +UnexpectedCharacter: . -> channel(ERROR); + +mode TEMPLATE; + +TemplateStringEscapeAtom: '\\' .; +BackTickInside: '`' {this.decreaseTemplateDepth();} -> type(BackTick), popMode; +TemplateStringStartExpression: '${' {this.startTemplateString();} -> pushMode(DEFAULT_MODE); +TemplateStringAtom: ~[`\\]; + +// Fragment rules + +fragment DoubleStringCharacter + : ~["\\\r\n] + | '\\' EscapeSequence + | LineContinuation + ; + +fragment SingleStringCharacter + : ~['\\\r\n] + | '\\' EscapeSequence + | LineContinuation + ; + +fragment EscapeSequence + : CharacterEscapeSequence + | '0' // no digit ahead! TODO + | HexEscapeSequence + | UnicodeEscapeSequence + | ExtendedUnicodeEscapeSequence + ; + +fragment CharacterEscapeSequence + : SingleEscapeCharacter + | NonEscapeCharacter + ; + +fragment HexEscapeSequence + : 'x' HexDigit HexDigit + ; + +fragment UnicodeEscapeSequence + : 'u' HexDigit HexDigit HexDigit HexDigit + ; + +fragment ExtendedUnicodeEscapeSequence + : 'u' '{' HexDigit+ '}' + ; + +fragment SingleEscapeCharacter + : ['"\\bfnrtv] + ; + +fragment NonEscapeCharacter + : ~['"\\bfnrtv0-9xu\r\n] + ; + +fragment EscapeCharacter + : SingleEscapeCharacter + | [0-9] + | [xu] + ; + +fragment LineContinuation + : '\\' [\r\n\u2028\u2029] + ; + +fragment HexDigit + : [0-9a-fA-F] + ; + +fragment DecimalIntegerLiteral + : '0' + | [1-9] [0-9]* + ; + +fragment ExponentPart + : [eE] [+-]? [0-9]+ + ; + +fragment IdentifierPart + : IdentifierStart + | [\p{Mn}] + | [\p{Nd}] + | [\p{Pc}] + | '\u200C' + | '\u200D' + ; + +fragment IdentifierStart + : [\p{L}] + | [$_] + | '\\' UnicodeEscapeSequence + ; + +fragment RegularExpressionFirstChar + : ~[*\r\n\u2028\u2029\\/[] + | RegularExpressionBackslashSequence + | '[' RegularExpressionClassChar* ']' + ; + +fragment RegularExpressionChar + : ~[\r\n\u2028\u2029\\/[] + | RegularExpressionBackslashSequence + | '[' RegularExpressionClassChar* ']' + ; + +fragment RegularExpressionClassChar + : ~[\r\n\u2028\u2029\]\\] + | RegularExpressionBackslashSequence + ; + +fragment RegularExpressionBackslashSequence + : '\\' ~[\r\n\u2028\u2029] + ; + diff --git a/languages/typescript/src/main/antlr4/de/jplag/typescript/grammar/TypeScriptParser.g4 b/languages/typescript/src/main/antlr4/de/jplag/typescript/grammar/TypeScriptParser.g4 new file mode 100644 index 000000000..6e81b63ea --- /dev/null +++ b/languages/typescript/src/main/antlr4/de/jplag/typescript/grammar/TypeScriptParser.g4 @@ -0,0 +1,854 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2014 by Bart Kiers (original author) and Alexandre Vitorelli (contributor -> ported to CSharp) + * Copyright (c) 2017 by Ivan Kochurkin (Positive Technologies): + added ECMAScript 6 support, cleared and transformed to the universal grammar. + * Copyright (c) 2018 by Juan Alvarez (contributor -> ported to Go) + * Copyright (c) 2019 by Andrii Artiushok (contributor -> added TypeScript support) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +parser grammar TypeScriptParser; + +options { + tokenVocab=TypeScriptLexer; + superClass=TypeScriptParserBase; +} + +// SupportSyntax + +initializer + : '=' singleExpression + ; + +bindingPattern + : (arrayLiteral | objectLiteral) + ; + +// TypeScript SPart +// A.1 Types + +typeParameters + : '<' typeParameterList? '>' + ; + +typeParameterList + : typeParameter (',' typeParameter)* + ; + +typeParameter + : Identifier constraint? + | typeParameters + ; + +constraint + : 'extends' type_ + ; + +typeArguments + : '<' typeArgumentList? '>' + ; + +typeArgumentList + : typeArgument (',' typeArgument)* + ; + +typeArgument + : type_ + ; + +type_ + : unionOrIntersectionOrPrimaryType + | functionType + | constructorType + | typeGeneric + | StringLiteral + ; + +unionOrIntersectionOrPrimaryType + : unionOrIntersectionOrPrimaryType '|' unionOrIntersectionOrPrimaryType #Union + | unionOrIntersectionOrPrimaryType '&' unionOrIntersectionOrPrimaryType #Intersection + | primaryType #Primary + ; + +primaryType + : '(' type_ ')' #ParenthesizedPrimType + | predefinedType #PredefinedPrimType + | typeReference #ReferencePrimType + | objectType #ObjectPrimType + | primaryType {notLineTerminator()}? '[' ']' #ArrayPrimType + | '[' tupleElementTypes ']' #TuplePrimType + | typeQuery #QueryPrimType + | This #ThisPrimType + | typeReference Is primaryType #RedefinitionOfType + ; + +predefinedType + : Any + | Number + | Boolean + | String + | Symbol + | Void + ; + +typeReference + : typeName nestedTypeGeneric? + ; + +nestedTypeGeneric + : typeIncludeGeneric + | typeGeneric + ; + +// I tried recursive include, but it's not working. +// typeGeneric +// : '<' typeArgumentList typeGeneric?'>' +// ; +// +// TODO: Fix recursive +// +typeGeneric + : '<' typeArgumentList '>' + ; + +typeIncludeGeneric + :'<' typeArgumentList '<' typeArgumentList ('>' bindingPattern '>' | '>>') + ; + +typeName + : Identifier + | namespaceName + ; + +objectType + : '{' typeBody? '}' + ; + +typeBody + : typeMemberList (SemiColon | ',')? + ; + +typeMemberList + : typeMember ((SemiColon | ',') typeMember)* + ; + +typeMember + : propertySignatur + | callSignature + | constructSignature + | indexSignature + | methodSignature ('=>' type_)? + ; + +arrayType + : primaryType {notLineTerminator()}? '[' ']' + ; + +tupleType + : '[' tupleElementTypes ']' + ; + +tupleElementTypes + : type_ (',' type_)* + ; + +functionType + : typeParameters? '(' parameterList? ')' '=>' type_ + ; + +constructorType + : 'new' typeParameters? '(' parameterList? ')' '=>' type_ + ; + +typeQuery + : 'typeof' typeQueryExpression + ; + +typeQueryExpression + : Identifier + | (identifierName '.')+ identifierName + ; + +propertySignatur + : ReadOnly? propertyName '?'? typeAnnotation? ('=>' type_)? + ; + +typeAnnotation + : ':' type_ + ; + +callSignature + : typeParameters? '(' parameterList? ')' typeAnnotation? + ; + +parameterList + : restParameter + | parameter (',' parameter)* (',' restParameter)? + ; + +requiredParameterList + : requiredParameter (',' requiredParameter)* + ; + +parameter + : requiredParameter + | optionalParameter + ; + +optionalParameter + : decoratorList? ( accessibilityModifier? identifierOrPattern ('?' typeAnnotation? | typeAnnotation? initializer)) + ; + +restParameter + : '...' singleExpression typeAnnotation? + ; + +requiredParameter + : decoratorList? accessibilityModifier? identifierOrPattern typeAnnotation? + ; + +accessibilityModifier + : Public + | Private + | Protected + ; + +identifierOrPattern + : identifierName + | bindingPattern + ; + +constructSignature + : 'new' typeParameters? '(' parameterList? ')' typeAnnotation? + ; + +indexSignature + : '[' Identifier ':' (Number|String) ']' typeAnnotation + ; + +methodSignature + : propertyName '?'? callSignature + ; + +typeAliasDeclaration + : 'type' Identifier typeParameters? '=' type_ SemiColon + ; + +constructorDeclaration + : accessibilityModifier? Constructor '(' formalParameterList? ')' ( ('{' functionBody '}') | SemiColon)? + ; + +// A.5 Interface + +interfaceDeclaration + : Export? Declare? Interface Identifier typeParameters? interfaceExtendsClause? objectType SemiColon? + ; + +interfaceExtendsClause + : Extends classOrInterfaceTypeList + ; + +classOrInterfaceTypeList + : typeReference (',' typeReference)* + ; + +// A.7 Interface + +enumDeclaration + : Const? Enum Identifier '{' enumBody? '}' + ; + +enumBody + : enumMemberList ','? + ; + +enumMemberList + : enumMember (',' enumMember)* + ; + +enumMember + : propertyName ('=' singleExpression)? + ; + +// A.8 Namespaces + +namespaceDeclaration + : Namespace namespaceName '{' statementList? '}' + ; + +namespaceName + : Identifier ('.'+ Identifier)* + ; + +importAliasDeclaration + : Identifier '=' namespaceName SemiColon + ; + +// Ext.2 Additions to 1.8: Decorators + +decoratorList + : decorator+ ; + +decorator + : '@' (decoratorMemberExpression | decoratorCallExpression) + ; + +decoratorMemberExpression + : Identifier + | decoratorMemberExpression '.' identifierName + | '(' singleExpression ')' + ; + +decoratorCallExpression + : decoratorMemberExpression arguments; + +// ECMAPart +program + : sourceElements? EOF + ; + +sourceElement + : Export? statement + ; + +statement + : block + | importStatement + | exportStatement + | emptyStatement_ + | abstractDeclaration //ADDED + | classDeclaration + | interfaceDeclaration //ADDED + | namespaceDeclaration //ADDED + | ifStatement + | iterationStatement + | continueStatement + | breakStatement + | returnStatement + | yieldStatement + | withStatement + | labelledStatement + | switchStatement + | throwStatement + | tryStatement + | debuggerStatement + | functionDeclaration + | arrowFunctionDeclaration + | generatorFunctionDeclaration + | variableStatement + | typeAliasDeclaration //ADDED + | enumDeclaration //ADDED + | expressionStatement + | Export statement + ; + +block + : '{' statementList? '}' + ; + +statementList + : statement+ + ; + +abstractDeclaration + : Abstract (Identifier callSignature | variableStatement) eos + ; + +importStatement + : Import (fromBlock | importAliasDeclaration) + ; + +fromBlock + : (Multiply | multipleImportStatement) (As identifierName)? From StringLiteral eos + ; + +multipleImportStatement + : (identifierName ',')? '{' identifierName (',' identifierName)* '}' + ; + +exportStatement + : Export Default? (fromBlock | statement) + ; + +variableStatement + : bindingPattern typeAnnotation? initializer SemiColon? + | accessibilityModifier? varModifier? ReadOnly? variableDeclarationList SemiColon? + | Declare varModifier? variableDeclarationList SemiColon? + ; + +variableDeclarationList + : variableDeclaration (',' variableDeclaration)* + ; + +variableDeclaration + : ( identifierOrKeyWord | arrayLiteral | objectLiteral) typeAnnotation? singleExpression? ('=' typeParameters? singleExpression)? // ECMAScript 6: Array & Object Matching + ; + +emptyStatement_ + : SemiColon + ; + +expressionStatement + : {this.notOpenBraceAndNotFunction()}? expressionSequence SemiColon? + ; + +ifStatement + : If '(' expressionSequence ')' statement (Else statement)? + ; + + +iterationStatement + : Do statement While '(' expressionSequence ')' eos # DoStatement + | While '(' expressionSequence ')' statement # WhileStatement + | For '(' expressionSequence? SemiColon expressionSequence? SemiColon expressionSequence? ')' statement # ForStatement + | For '(' varModifier variableDeclarationList SemiColon expressionSequence? SemiColon expressionSequence? ')' + statement # ForVarStatement + | For '(' singleExpression (In | Identifier{this.p("of")}?) expressionSequence ')' statement # ForInStatement + | For '(' varModifier variableDeclaration (In | Identifier{this.p("of")}?) expressionSequence ')' statement # ForVarInStatement + ; + +varModifier + : Var + | Let + | Const + ; + +continueStatement + : Continue ({this.notLineTerminator()}? Identifier)? eos + ; + +breakStatement + : Break ({this.notLineTerminator()}? Identifier)? eos + ; + +returnStatement + : Return ({this.notLineTerminator()}? expressionSequence)? eos + ; + +yieldStatement + : Yield ({this.notLineTerminator()}? expressionSequence)? eos + ; + +withStatement + : With '(' expressionSequence ')' statement + ; + +switchStatement + : Switch '(' expressionSequence ')' caseBlock + ; + +caseBlock + : '{' caseClauses? (defaultClause caseClauses?)? '}' + ; + +caseClauses + : caseClause+ + ; + +caseClause + : Case expressionSequence ':' statementList? + ; + +defaultClause + : Default ':' statementList? + ; + +labelledStatement + : Identifier ':' statement + ; + +throwStatement + : Throw {this.notLineTerminator()}? expressionSequence eos + ; + +tryStatement + : Try block (catchProduction finallyProduction? | finallyProduction) + ; + +catchProduction + : Catch '(' Identifier ')' block + ; + +finallyProduction + : Finally block + ; + +debuggerStatement + : Debugger eos + ; + +functionDeclaration + : Function_ Identifier callSignature ( ('{' functionBody '}') | SemiColon) + ; + +//Ovveride ECMA +classDeclaration + : decoratorList? (Export Default?)? Abstract? Class Identifier typeParameters? classHeritage classTail + ; + +classHeritage + : classExtendsClause? implementsClause? + ; + +classTail + : '{' classElement* '}' + ; + +classExtendsClause + : Extends typeReference + ; + +implementsClause + : Implements classOrInterfaceTypeList + ; + +// Classes modified +classElement + : constructorDeclaration + | decoratorList? propertyMemberDeclaration + | indexMemberDeclaration + | statement + ; + +propertyMemberDeclaration + : propertyMemberBase propertyName '?'? typeAnnotation? initializer? SemiColon # PropertyDeclarationExpression + | propertyMemberBase propertyName callSignature ( ('{' functionBody '}') | SemiColon) # MethodDeclarationExpression + | propertyMemberBase (getAccessor | setAccessor) # GetterSetterDeclarationExpression + | abstractDeclaration # AbstractMemberDeclaration + ; + +propertyMemberBase + : accessibilityModifier? Async? Static? ReadOnly? + ; + +indexMemberDeclaration + : indexSignature SemiColon + ; + +generatorMethod + : '*'? Identifier '(' formalParameterList? ')' '{' functionBody '}' + ; + +generatorFunctionDeclaration + : Function_ '*' Identifier? '(' formalParameterList? ')' '{' functionBody '}' + ; + +generatorBlock + : '{' generatorDefinition (',' generatorDefinition)* ','? '}' + ; + +generatorDefinition + : '*' iteratorDefinition + ; + +iteratorBlock + : '{' iteratorDefinition (',' iteratorDefinition)* ','? '}' + ; + +iteratorDefinition + : '[' singleExpression ']' '(' formalParameterList? ')' '{' functionBody '}' + ; + +formalParameterList + : formalParameterArg (',' formalParameterArg)* (',' lastFormalParameterArg)? + | lastFormalParameterArg + | arrayLiteral // ECMAScript 6: Parameter Context Matching + | objectLiteral (':' formalParameterList)? // ECMAScript 6: Parameter Context Matching + ; + +formalParameterArg + : decorator? accessibilityModifier? identifierOrKeyWord '?'? typeAnnotation? ('=' singleExpression)? // ECMAScript 6: Initialization + ; + +lastFormalParameterArg // ECMAScript 6: Rest Parameter + : Ellipsis Identifier typeAnnotation? + ; + +functionBody + : sourceElements? + ; + +sourceElements + : sourceElement+ + ; + +arrayLiteral + : ('[' elementList? ']') + ; + +elementList + : arrayElement (','+ arrayElement)* + ; + +arrayElement // ECMAScript 6: Spread Operator + : Ellipsis? (singleExpression | Identifier) ','? + ; + +objectLiteral + : '{' (propertyAssignment (',' propertyAssignment)* ','?)? '}' + ; + +// MODIFIED +propertyAssignment + : propertyName (':' |'=') singleExpression # PropertyExpressionAssignment + | '[' singleExpression ']' ':' singleExpression # ComputedPropertyExpressionAssignment + | getAccessor # PropertyGetter + | setAccessor # PropertySetter + | generatorMethod # MethodProperty + | identifierOrKeyWord # PropertyShorthand + | restParameter # RestParameterInObject + ; + +getAccessor + : getter '(' ')' typeAnnotation? '{' functionBody '}' + ; + +setAccessor + : setter '(' ( Identifier | bindingPattern) typeAnnotation? ')' '{' functionBody '}' + ; + +propertyName + : identifierName + | StringLiteral + | numericLiteral + ; + +arguments + : '(' (argumentList ','?)? ')' + ; + +argumentList + : argument (',' argument)* + ; + +argument // ECMAScript 6: Spread Operator + : Ellipsis? (singleExpression | Identifier) + ; + +expressionSequence + : singleExpression (',' singleExpression)* + ; + +functionExpressionDeclaration + : Function_ Identifier? '(' formalParameterList? ')' typeAnnotation? '{' functionBody '}' + ; + +singleExpression + : functionExpressionDeclaration # FunctionExpression + | arrowFunctionDeclaration # ArrowFunctionExpression // ECMAScript 6 + | singleExpression '[' expressionSequence ']' # MemberIndexExpression + | singleExpression '!'? '.' identifierName nestedTypeGeneric? # MemberDotExpression + // Split to try `new Date()` first, then `new Date`. + | New singleExpression typeArguments? arguments # NewExpression + | New singleExpression typeArguments? # NewExpression + | singleExpression arguments # ArgumentsExpression + | singleExpression {this.notLineTerminator()}? '++' # PostIncrementExpression + | singleExpression {this.notLineTerminator()}? '--' # PostDecreaseExpression + | Delete singleExpression # DeleteExpression + | Void singleExpression # VoidExpression + | Typeof singleExpression # TypeofExpression + | '++' singleExpression # PreIncrementExpression + | '--' singleExpression # PreDecreaseExpression + | '+' singleExpression # UnaryPlusExpression + | '-' singleExpression # UnaryMinusExpression + | '~' singleExpression # BitNotExpression + | '!' singleExpression # NotExpression + | singleExpression ('*' | '/' | '%') singleExpression # MultiplicativeExpression + | singleExpression ('+' | '-') singleExpression # AdditiveExpression + | singleExpression ('<<' | '>>' | '>>>') singleExpression # BitShiftExpression + | singleExpression ('<' | '>' | '<=' | '>=') singleExpression # RelationalExpression + | singleExpression Instanceof singleExpression # InstanceofExpression + | singleExpression In singleExpression # InExpression + | singleExpression ('==' | '!=' | '===' | '!==') singleExpression # EqualityExpression + | singleExpression '&' singleExpression # BitAndExpression + | singleExpression '^' singleExpression # BitXOrExpression + | singleExpression '|' singleExpression # BitOrExpression + | singleExpression '&&' singleExpression # LogicalAndExpression + | singleExpression '||' singleExpression # LogicalOrExpression + | singleExpression '?' singleExpression ':' singleExpression # TernaryExpression + | singleExpression '=' singleExpression # AssignmentExpression + | singleExpression assignmentOperator singleExpression # AssignmentOperatorExpression + | singleExpression templateStringLiteral # TemplateStringExpression // ECMAScript 6 + | iteratorBlock # IteratorsExpression // ECMAScript 6 + | generatorBlock # GeneratorsExpression // ECMAScript 6 + | generatorFunctionDeclaration # GeneratorsFunctionExpression // ECMAScript 6 + | yieldStatement # YieldExpression // ECMAScript 6 + | This # ThisExpression + | identifierName singleExpression? # IdentifierExpression + | Super # SuperExpression + | literal # LiteralExpression + | arrayLiteral # ArrayLiteralExpression + | objectLiteral # ObjectLiteralExpression + | '(' expressionSequence ')' # ParenthesizedExpression + | typeArguments expressionSequence? # GenericTypes + | singleExpression As asExpression # CastAsExpression + ; + +asExpression + : predefinedType ('[' ']')? + | singleExpression + ; + +arrowFunctionDeclaration + : Async? arrowFunctionParameters typeAnnotation? '=>' arrowFunctionBody + ; + +arrowFunctionParameters + : Identifier + | '(' formalParameterList? ')' + ; + +arrowFunctionBody + : singleExpression + | '{' functionBody '}' + ; + +assignmentOperator + : '*=' + | '/=' + | '%=' + | '+=' + | '-=' + | '<<=' + | '>>=' + | '>>>=' + | '&=' + | '^=' + | '|=' + ; + +literal + : NullLiteral + | BooleanLiteral + | StringLiteral + | templateStringLiteral + | RegularExpressionLiteral + | numericLiteral + ; + +templateStringLiteral + : BackTick templateStringAtom* BackTick + ; + +templateStringAtom + : TemplateStringAtom + | TemplateStringStartExpression singleExpression TemplateCloseBrace + | TemplateStringEscapeAtom + ; + +numericLiteral + : DecimalLiteral + | HexIntegerLiteral + | OctalIntegerLiteral + | OctalIntegerLiteral2 + | BinaryIntegerLiteral + ; + +identifierName + : Identifier + | reservedWord + ; + +identifierOrKeyWord + : Identifier + | TypeAlias + | Require + ; + +reservedWord + : keyword + | NullLiteral + | BooleanLiteral + ; + +keyword + : Break + | Do + | Instanceof + | Typeof + | Case + | Else + | New + | Var + | Catch + | Finally + | Return + | Void + | Continue + | For + | Switch + | While + | Debugger + | Function_ + | This + | With + | Default + | If + | Throw + | Delete + | In + | Try + | ReadOnly + | Async + | From + | Class + | Enum + | Extends + | Super + | Const + | Export + | Import + | Implements + | Let + | Private + | Public + | Interface + | Package + | Protected + | Static + | Yield + | Get + | Set + | Require + | TypeAlias + | String + | Boolean + | Number + | Module + ; + +getter + : Get propertyName + ; + +setter + : Set propertyName + ; + +eos + : SemiColon + | EOF + | {this.lineTerminatorAhead()}? + | {this.closeBrace()}? + ; diff --git a/languages/typescript/src/main/java/de/jplag/typescript/TypeScriptLanguage.java b/languages/typescript/src/main/java/de/jplag/typescript/TypeScriptLanguage.java new file mode 100644 index 000000000..d6f1fbb0a --- /dev/null +++ b/languages/typescript/src/main/java/de/jplag/typescript/TypeScriptLanguage.java @@ -0,0 +1,45 @@ +package de.jplag.typescript; + +import org.kohsuke.MetaInfServices; + +import de.jplag.antlr.AbstractAntlrLanguage; + +/** + * This represents the TypeScript language as a language supported by JPlag. + */ +@MetaInfServices(de.jplag.Language.class) +public class TypeScriptLanguage extends AbstractAntlrLanguage { + + private static final String IDENTIFIER = "typescript"; + private final TypeScriptLanguageOptions options = new TypeScriptLanguageOptions(); + + @Override + public String[] suffixes() { + return new String[] {".ts", ".js"}; + } + + @Override + public String getName() { + return "Typescript Parser"; + } + + @Override + public String getIdentifier() { + return IDENTIFIER; + } + + @Override + public int minimumTokenMatch() { + return 12; + } + + @Override + public TypeScriptLanguageOptions getOptions() { + return options; + } + + @Override + protected TypeScriptParserAdapter initializeParser() { + return new TypeScriptParserAdapter(getOptions().useStrictDefault()); + } +} diff --git a/languages/typescript/src/main/java/de/jplag/typescript/TypeScriptLanguageOptions.java b/languages/typescript/src/main/java/de/jplag/typescript/TypeScriptLanguageOptions.java new file mode 100644 index 000000000..8a01976c0 --- /dev/null +++ b/languages/typescript/src/main/java/de/jplag/typescript/TypeScriptLanguageOptions.java @@ -0,0 +1,22 @@ +package de.jplag.typescript; + +import de.jplag.options.LanguageOption; +import de.jplag.options.LanguageOptions; +import de.jplag.options.OptionType; + +/** + * Language Specific options for the TypeScript language + */ +public class TypeScriptLanguageOptions extends LanguageOptions { + + /** + * Whether the Antlr Grammar should parse + */ + private final LanguageOption useStrictDefault = createDefaultOption(OptionType.bool(), "useStrictMode", + "If set JPlag parses files with the JavaScript strict syntax", false); + + public boolean useStrictDefault() { + return this.useStrictDefault.getValue(); + } + +} diff --git a/languages/typescript/src/main/java/de/jplag/typescript/TypeScriptListener.java b/languages/typescript/src/main/java/de/jplag/typescript/TypeScriptListener.java new file mode 100644 index 000000000..31dc21378 --- /dev/null +++ b/languages/typescript/src/main/java/de/jplag/typescript/TypeScriptListener.java @@ -0,0 +1,146 @@ +package de.jplag.typescript; + +import static de.jplag.typescript.TypeScriptTokenType.ASSIGNMENT; +import static de.jplag.typescript.TypeScriptTokenType.BREAK; +import static de.jplag.typescript.TypeScriptTokenType.CATCH_BEGIN; +import static de.jplag.typescript.TypeScriptTokenType.CATCH_END; +import static de.jplag.typescript.TypeScriptTokenType.CLASS_BEGIN; +import static de.jplag.typescript.TypeScriptTokenType.CLASS_END; +import static de.jplag.typescript.TypeScriptTokenType.CONSTRUCTOR_BEGIN; +import static de.jplag.typescript.TypeScriptTokenType.CONSTRUCTOR_END; +import static de.jplag.typescript.TypeScriptTokenType.CONTINUE; +import static de.jplag.typescript.TypeScriptTokenType.DECLARATION; +import static de.jplag.typescript.TypeScriptTokenType.ENUM_BEGIN; +import static de.jplag.typescript.TypeScriptTokenType.ENUM_END; +import static de.jplag.typescript.TypeScriptTokenType.ENUM_MEMBER; +import static de.jplag.typescript.TypeScriptTokenType.EXPORT; +import static de.jplag.typescript.TypeScriptTokenType.FINALLY_BEGIN; +import static de.jplag.typescript.TypeScriptTokenType.FINALLY_END; +import static de.jplag.typescript.TypeScriptTokenType.FOR_BEGIN; +import static de.jplag.typescript.TypeScriptTokenType.FOR_END; +import static de.jplag.typescript.TypeScriptTokenType.FUNCTION_CALL; +import static de.jplag.typescript.TypeScriptTokenType.IF_BEGIN; +import static de.jplag.typescript.TypeScriptTokenType.IF_END; +import static de.jplag.typescript.TypeScriptTokenType.IMPORT; +import static de.jplag.typescript.TypeScriptTokenType.INTERFACE_BEGIN; +import static de.jplag.typescript.TypeScriptTokenType.INTERFACE_END; +import static de.jplag.typescript.TypeScriptTokenType.METHOD_BEGIN; +import static de.jplag.typescript.TypeScriptTokenType.METHOD_END; +import static de.jplag.typescript.TypeScriptTokenType.NAMESPACE_BEGIN; +import static de.jplag.typescript.TypeScriptTokenType.NAMESPACE_END; +import static de.jplag.typescript.TypeScriptTokenType.RETURN; +import static de.jplag.typescript.TypeScriptTokenType.SWITCH_BEGIN; +import static de.jplag.typescript.TypeScriptTokenType.SWITCH_CASE; +import static de.jplag.typescript.TypeScriptTokenType.SWITCH_END; +import static de.jplag.typescript.TypeScriptTokenType.THROW; +import static de.jplag.typescript.TypeScriptTokenType.TRY_BEGIN; +import static de.jplag.typescript.TypeScriptTokenType.WHILE_BEGIN; +import static de.jplag.typescript.TypeScriptTokenType.WHILE_END; +import static de.jplag.typescript.grammar.TypeScriptParser.ArgumentsContext; +import static de.jplag.typescript.grammar.TypeScriptParser.ArrowFunctionDeclarationContext; +import static de.jplag.typescript.grammar.TypeScriptParser.AssignmentExpressionContext; +import static de.jplag.typescript.grammar.TypeScriptParser.BreakStatementContext; +import static de.jplag.typescript.grammar.TypeScriptParser.CaseClauseContext; +import static de.jplag.typescript.grammar.TypeScriptParser.CatchProductionContext; +import static de.jplag.typescript.grammar.TypeScriptParser.ClassDeclarationContext; +import static de.jplag.typescript.grammar.TypeScriptParser.ConstructorDeclarationContext; +import static de.jplag.typescript.grammar.TypeScriptParser.ContinueStatementContext; +import static de.jplag.typescript.grammar.TypeScriptParser.DefaultClauseContext; +import static de.jplag.typescript.grammar.TypeScriptParser.Else; +import static de.jplag.typescript.grammar.TypeScriptParser.EnumDeclarationContext; +import static de.jplag.typescript.grammar.TypeScriptParser.EnumMemberContext; +import static de.jplag.typescript.grammar.TypeScriptParser.Export; +import static de.jplag.typescript.grammar.TypeScriptParser.FinallyProductionContext; +import static de.jplag.typescript.grammar.TypeScriptParser.ForInStatementContext; +import static de.jplag.typescript.grammar.TypeScriptParser.ForStatementContext; +import static de.jplag.typescript.grammar.TypeScriptParser.ForVarStatementContext; +import static de.jplag.typescript.grammar.TypeScriptParser.FunctionDeclarationContext; +import static de.jplag.typescript.grammar.TypeScriptParser.FunctionExpressionDeclarationContext; +import static de.jplag.typescript.grammar.TypeScriptParser.GetterSetterDeclarationExpressionContext; +import static de.jplag.typescript.grammar.TypeScriptParser.IfStatementContext; +import static de.jplag.typescript.grammar.TypeScriptParser.ImportStatementContext; +import static de.jplag.typescript.grammar.TypeScriptParser.InterfaceDeclarationContext; +import static de.jplag.typescript.grammar.TypeScriptParser.MethodDeclarationExpressionContext; +import static de.jplag.typescript.grammar.TypeScriptParser.NamespaceDeclarationContext; +import static de.jplag.typescript.grammar.TypeScriptParser.PostDecreaseExpressionContext; +import static de.jplag.typescript.grammar.TypeScriptParser.PostIncrementExpressionContext; +import static de.jplag.typescript.grammar.TypeScriptParser.PreDecreaseExpressionContext; +import static de.jplag.typescript.grammar.TypeScriptParser.PreIncrementExpressionContext; +import static de.jplag.typescript.grammar.TypeScriptParser.PropertyDeclarationExpressionContext; +import static de.jplag.typescript.grammar.TypeScriptParser.PropertySetterContext; +import static de.jplag.typescript.grammar.TypeScriptParser.PropertySignaturContext; +import static de.jplag.typescript.grammar.TypeScriptParser.ReturnStatementContext; +import static de.jplag.typescript.grammar.TypeScriptParser.SwitchStatementContext; +import static de.jplag.typescript.grammar.TypeScriptParser.ThrowStatementContext; +import static de.jplag.typescript.grammar.TypeScriptParser.TryStatementContext; +import static de.jplag.typescript.grammar.TypeScriptParser.VariableDeclarationContext; +import static de.jplag.typescript.grammar.TypeScriptParser.WhileStatementContext; + +import de.jplag.antlr.AbstractAntlrListener; + +/** + * This class is responsible for mapping parsed TypeScript to the internal Token structure + */ +public class TypeScriptListener extends AbstractAntlrListener { + + public TypeScriptListener() { + visit(ImportStatementContext.class).map(IMPORT); + visit(Export).map(EXPORT); + visit(NamespaceDeclarationContext.class).map(NAMESPACE_BEGIN, NAMESPACE_END); + + visit(ClassDeclarationContext.class).map(CLASS_BEGIN, CLASS_END); + visit(GetterSetterDeclarationExpressionContext.class).map(METHOD_BEGIN, METHOD_END); + visit(PropertyDeclarationExpressionContext.class).map(DECLARATION); + visit(PropertyDeclarationExpressionContext.class, it -> it.initializer() != null).map(ASSIGNMENT); + visit(PropertySetterContext.class).map(ASSIGNMENT); + visit(PropertySignaturContext.class).map(DECLARATION); + + visit(InterfaceDeclarationContext.class).map(INTERFACE_BEGIN, INTERFACE_END); + visit(ConstructorDeclarationContext.class).map(CONSTRUCTOR_BEGIN, CONSTRUCTOR_END); + + visit(EnumDeclarationContext.class).map(ENUM_BEGIN, ENUM_END); + visit(EnumMemberContext.class).map(ENUM_MEMBER); + + visit(VariableDeclarationContext.class).map(DECLARATION); + visit(VariableDeclarationContext.class, it -> it.Assign() != null).map(ASSIGNMENT); + + visit(IfStatementContext.class).map(IF_BEGIN, IF_END); + visit(Else).map(IF_BEGIN); + + visit(SwitchStatementContext.class).map(SWITCH_BEGIN, SWITCH_END); + visit(CaseClauseContext.class).map(SWITCH_CASE); + visit(DefaultClauseContext.class).map(SWITCH_CASE); + + visit(MethodDeclarationExpressionContext.class).map(METHOD_BEGIN, METHOD_END); + + visit(FunctionDeclarationContext.class).map(DECLARATION); + visit(FunctionDeclarationContext.class).map(ASSIGNMENT); + visit(FunctionDeclarationContext.class).map(METHOD_BEGIN, METHOD_END); + + visit(ArrowFunctionDeclarationContext.class).map(METHOD_BEGIN, METHOD_END); + visit(FunctionExpressionDeclarationContext.class).map(METHOD_BEGIN, METHOD_END); + + visit(WhileStatementContext.class).map(WHILE_BEGIN, WHILE_END); + visit(ForStatementContext.class).map(FOR_BEGIN, FOR_END); + visit(ForVarStatementContext.class).map(FOR_BEGIN, FOR_END); + visit(ForInStatementContext.class).map(FOR_BEGIN, FOR_END); + + visit(TryStatementContext.class).map(TRY_BEGIN); + visit(CatchProductionContext.class).map(CATCH_BEGIN, CATCH_END); + visit(FinallyProductionContext.class).map(FINALLY_BEGIN, FINALLY_END); + + visit(BreakStatementContext.class).map(BREAK); + visit(ReturnStatementContext.class).map(RETURN); + visit(ContinueStatementContext.class).map(CONTINUE); + visit(ThrowStatementContext.class).map(THROW); + + visit(AssignmentExpressionContext.class).map(ASSIGNMENT); + visit(PostDecreaseExpressionContext.class).map(ASSIGNMENT); + visit(PreDecreaseExpressionContext.class).map(ASSIGNMENT); + visit(PostIncrementExpressionContext.class).map(ASSIGNMENT); + visit(PreIncrementExpressionContext.class).map(ASSIGNMENT); + + visit(ArgumentsContext.class).map(FUNCTION_CALL); + } + +} diff --git a/languages/typescript/src/main/java/de/jplag/typescript/TypeScriptParserAdapter.java b/languages/typescript/src/main/java/de/jplag/typescript/TypeScriptParserAdapter.java new file mode 100644 index 000000000..837512053 --- /dev/null +++ b/languages/typescript/src/main/java/de/jplag/typescript/TypeScriptParserAdapter.java @@ -0,0 +1,49 @@ +package de.jplag.typescript; + +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.ParserRuleContext; + +import de.jplag.antlr.AbstractAntlrListener; +import de.jplag.antlr.AbstractAntlrParserAdapter; +import de.jplag.typescript.grammar.TypeScriptLexer; +import de.jplag.typescript.grammar.TypeScriptParser; + +/** + * The Antlr adapter used for the TypeScript language module + */ +public class TypeScriptParserAdapter extends AbstractAntlrParserAdapter { + private static final TypeScriptListener listener = new TypeScriptListener(); + private final boolean useStrictDefault; + + /** + * Creates a new Parser adapter for the Typescript Antlr Grammar + * @param useStrictDefault True if the grammars should parse the files using the JavaScript strict syntax + */ + public TypeScriptParserAdapter(boolean useStrictDefault) { + this.useStrictDefault = useStrictDefault; + } + + @Override + protected Lexer createLexer(CharStream input) { + TypeScriptLexer lexer = new TypeScriptLexer(input); + lexer.setUseStrictDefault(useStrictDefault); + return lexer; + } + + @Override + protected TypeScriptParser createParser(CommonTokenStream tokenStream) { + return new TypeScriptParser(tokenStream); + } + + @Override + protected ParserRuleContext getEntryContext(TypeScriptParser parser) { + return parser.sourceElements(); + } + + @Override + protected AbstractAntlrListener getListener() { + return listener; + } +} diff --git a/languages/typescript/src/main/java/de/jplag/typescript/TypeScriptTokenType.java b/languages/typescript/src/main/java/de/jplag/typescript/TypeScriptTokenType.java new file mode 100644 index 000000000..da8b0f8da --- /dev/null +++ b/languages/typescript/src/main/java/de/jplag/typescript/TypeScriptTokenType.java @@ -0,0 +1,56 @@ +package de.jplag.typescript; + +import de.jplag.TokenType; + +/** + * Tokens extracted by the TypeScript language module + */ +public enum TypeScriptTokenType implements TokenType { + + IMPORT("IMPORT"), + EXPORT("EXPORT"), + NAMESPACE_BEGIN("NAMESPACE{"), + NAMESPACE_END("}NAMESPACE"), + CLASS_BEGIN("CLASS{"), + CLASS_END("}CLASS"), + INTERFACE_BEGIN("INTERFACE{"), + INTERFACE_END("}INTERFACE"), + ENUM_BEGIN("ENUM{"), + ENUM_END("}ENUM"), + METHOD_BEGIN("METHOD{"), + METHOD_END("}METHOD"), + WHILE_BEGIN("WHILE{"), + WHILE_END("}WHILE"), + FOR_BEGIN("FOR{"), + FOR_END("}FOR"), + ASSIGNMENT("ASSIGN"), + IF_BEGIN("IF{"), + IF_END("}IF"), + SWITCH_BEGIN("SWITCH{"), + SWITCH_END("}SWITCH"), + SWITCH_CASE("CASE"), + TRY_BEGIN("TRY{"), + CATCH_BEGIN("}CATCH{"), + CATCH_END("}CATCH"), + FINALLY_BEGIN("FINALLY{"), + FINALLY_END("}FINALLY"), + BREAK("BREAK"), + RETURN("RETURN"), + THROW("THROW"), + CONTINUE("CONTINUE"), + FUNCTION_CALL("CALL"), + ENUM_MEMBER("ENUM_MEMBER"), + CONSTRUCTOR_BEGIN("CONSTRUCT{"), + CONSTRUCTOR_END("}CONSTRUCT"), + DECLARATION("DECLARE"); + + private final String description; + + public String getDescription() { + return this.description; + } + + TypeScriptTokenType(String description) { + this.description = description; + } +} diff --git a/languages/typescript/src/main/java/de/jplag/typescript/grammar/TypeScriptLexerBase.java b/languages/typescript/src/main/java/de/jplag/typescript/grammar/TypeScriptLexerBase.java new file mode 100644 index 000000000..d08aa4cb6 --- /dev/null +++ b/languages/typescript/src/main/java/de/jplag/typescript/grammar/TypeScriptLexerBase.java @@ -0,0 +1,133 @@ +package de.jplag.typescript.grammar; + +import java.util.ArrayDeque; +import java.util.Deque; + +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.Token; + +/** + * Copied from https://github.com/antlr/grammars-v4/tree/master/javascript/typescript/Java. Slightly modified to fit + * JPlag code style + */ +abstract class TypeScriptLexerBase extends Lexer { + /** + * Stores values of nested modes. By default mode is strict or defined externally (useStrictDefault) + */ + private final Deque scopeStrictModes = new ArrayDeque<>(); + + private Token lastToken = null; + /** + * Default value of strict mode Can be defined externally by setUseStrictDefault + */ + private boolean useStrictDefault = false; + /** + * Current value of strict mode Can be defined during parsing, see StringFunctions.js and StringGlobal.js samples + */ + private boolean useStrictCurrent = false; + /** + * Keeps track of the current depth of nested template string backticks. E.g. after the X in: `${a ? `${X templateDepth + * will be 2. This variable is needed to determine if a `}` is a plain CloseBrace, or one that closes an expression + * inside a template string. + */ + private int templateDepth = 0; + + private int openBracesCount = 0; + + protected TypeScriptLexerBase(CharStream input) { + super(input); + } + + public boolean getStrictDefault() { + return useStrictDefault; + } + + public void setUseStrictDefault(boolean value) { + useStrictDefault = value; + useStrictCurrent = value; + } + + public boolean isStrictMode() { + return useStrictCurrent; + } + + public void startTemplateString() { + this.openBracesCount = 0; + } + + public boolean isInTemplateString() { + return this.templateDepth > 0 && this.openBracesCount == 0; + } + + /** + * Return the next token from the character stream and records this last token in case it resides on the default + * channel. This recorded token is used to determine when the lexer could possibly match a regex literal. Also changes + * scopeStrictModes stack if tokenize special string 'use strict'; + * @return the next token from the character stream. + */ + @Override + public Token nextToken() { + Token next = super.nextToken(); + + if (next.getChannel() == Token.DEFAULT_CHANNEL) { + // Keep track of the last token on the default channel. + this.lastToken = next; + } + + return next; + } + + protected void processOpenBrace() { + openBracesCount++; + useStrictCurrent = !scopeStrictModes.isEmpty() && scopeStrictModes.peek() || useStrictDefault; + scopeStrictModes.push(useStrictCurrent); + } + + protected void processCloseBrace() { + openBracesCount--; + useStrictCurrent = scopeStrictModes.isEmpty() ? useStrictDefault : scopeStrictModes.pop(); + } + + protected void processStringLiteral() { + if (lastToken == null || lastToken.getType() == TypeScriptLexer.OpenBrace) { + String text = getText(); + if (text.equals("\"use strict\"") || text.equals("'use strict'")) { + if (!scopeStrictModes.isEmpty()) { + scopeStrictModes.pop(); + } + useStrictCurrent = true; + scopeStrictModes.push(true); + } + } + } + + protected void increaseTemplateDepth() { + this.templateDepth++; + } + + protected void decreaseTemplateDepth() { + this.templateDepth--; + } + + /** + * Returns {@code true} if the lexer can match a regex literal. + */ + protected boolean isRegexPossible() { + + if (this.lastToken == null) { + // No token has been produced yet: at the start of the input, + // no division is possible, so a regex literal _is_ possible. + return true; + } + + return switch (this.lastToken.getType()) { + case TypeScriptLexer.Identifier, TypeScriptLexer.NullLiteral, TypeScriptLexer.BooleanLiteral, TypeScriptLexer.This, TypeScriptLexer.CloseBracket, TypeScriptLexer.CloseParen, TypeScriptLexer.OctalIntegerLiteral, TypeScriptLexer.DecimalLiteral, TypeScriptLexer.HexIntegerLiteral, TypeScriptLexer.StringLiteral, TypeScriptLexer.PlusPlus, TypeScriptLexer.MinusMinus -> + // After any of the tokens above, no regex literal can follow. + false; + default -> + // In all other cases, a regex literal _is_ possible. + true; + }; + } +} \ No newline at end of file diff --git a/languages/typescript/src/main/java/de/jplag/typescript/grammar/TypeScriptParserBase.java b/languages/typescript/src/main/java/de/jplag/typescript/grammar/TypeScriptParserBase.java new file mode 100644 index 000000000..cf4c032cc --- /dev/null +++ b/languages/typescript/src/main/java/de/jplag/typescript/grammar/TypeScriptParserBase.java @@ -0,0 +1,113 @@ +package de.jplag.typescript.grammar; + +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.Parser; +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.TokenStream; + +/** + * All parser methods that used in grammar (p, prev, notLineTerminator, etc.) should start with lower case char similar + * to parser rules. Copied from https://github.com/antlr/grammars-v4/tree/master/javascript/typescript/Java. Slightly + * modified to fit JPlag code style + */ +public abstract class TypeScriptParserBase extends Parser { + protected TypeScriptParserBase(TokenStream input) { + super(input); + } + + /** + * Short form for prev(String str) + */ + protected boolean p(String str) { + return prev(str); + } + + /** + * Whether the previous token value equals to @param str + */ + protected boolean prev(String str) { + return _input.LT(-1).getText().equals(str); + } + + /** + * Short form for next(String str) + */ + protected boolean n(String str) { + return next(str); + } + + /** + * Whether the next token value equals to @param str + */ + protected boolean next(String str) { + return _input.LT(1).getText().equals(str); + } + + protected boolean notLineTerminator() { + return !here(TypeScriptParser.LineTerminator); + } + + protected boolean notOpenBraceAndNotFunction() { + int nextTokenType = _input.LT(1).getType(); + return nextTokenType != TypeScriptParser.OpenBrace && nextTokenType != TypeScriptParser.Function_; + } + + protected boolean closeBrace() { + return _input.LT(1).getType() == TypeScriptParser.CloseBrace; + } + + /** + * Returns {@code true} iff on the current index of the parser's token stream a token of the given {@code type} exists + * on the {@code HIDDEN} channel. + * @param type the type of the token on the {@code HIDDEN} channel to check. + * @return {@code true} iff on the current index of the parser's token stream a token of the given {@code type} exists + * on the {@code HIDDEN} channel. + */ + private boolean here(final int type) { + + // Get the token ahead of the current index. + int possibleIndexEosToken = this.getCurrentToken().getTokenIndex() - 1; + Token ahead = _input.get(possibleIndexEosToken); + + // Check if the token resides on the HIDDEN channel and if it's of the + // provided type. + return (ahead.getChannel() == Lexer.HIDDEN) && (ahead.getType() == type); + } + + /** + * Returns {@code true} iff on the current index of the parser's token stream a token exists on the {@code HIDDEN} + * channel which either is a line terminator, or is a multi line comment that contains a line terminator. + * @return {@code true} iff on the current index of the parser's token stream a token exists on the {@code HIDDEN} + * channel which either is a line terminator, or is a multi line comment that contains a line terminator. + */ + protected boolean lineTerminatorAhead() { + + // Get the token ahead of the current index. + int possibleIndexEosToken = this.getCurrentToken().getTokenIndex() - 1; + Token ahead = _input.get(possibleIndexEosToken); + + if (ahead.getChannel() != Lexer.HIDDEN) { + // We're only interested in tokens on the HIDDEN channel. + return false; + } + + if (ahead.getType() == TypeScriptParser.LineTerminator) { + // There is definitely a line terminator ahead. + return true; + } + + if (ahead.getType() == TypeScriptParser.WhiteSpaces) { + // Get the token ahead of the current whitespaces. + possibleIndexEosToken = this.getCurrentToken().getTokenIndex() - 2; + ahead = _input.get(possibleIndexEosToken); + } + + // Get the token's text and type. + String text = ahead.getText(); + int type = ahead.getType(); + + // Check if the token is, or contains a line terminator. + return (type == TypeScriptParser.MultiLineComment && (text.contains("\r") || text.contains("\n"))) + || (type == TypeScriptParser.LineTerminator); + } +} diff --git a/languages/typescript/src/test/java/de/jplag/typescript/JavaScriptLanguageTest.java b/languages/typescript/src/test/java/de/jplag/typescript/JavaScriptLanguageTest.java new file mode 100644 index 000000000..77c696a3f --- /dev/null +++ b/languages/typescript/src/test/java/de/jplag/typescript/JavaScriptLanguageTest.java @@ -0,0 +1,37 @@ +package de.jplag.typescript; + +import static de.jplag.typescript.TypeScriptTokenType.ENUM_BEGIN; +import static de.jplag.typescript.TypeScriptTokenType.ENUM_END; +import static de.jplag.typescript.TypeScriptTokenType.ENUM_MEMBER; +import static de.jplag.typescript.TypeScriptTokenType.INTERFACE_BEGIN; +import static de.jplag.typescript.TypeScriptTokenType.INTERFACE_END; +import static de.jplag.typescript.TypeScriptTokenType.NAMESPACE_BEGIN; +import static de.jplag.typescript.TypeScriptTokenType.NAMESPACE_END; + +import java.util.ArrayList; +import java.util.List; + +import de.jplag.TokenType; +import de.jplag.testutils.LanguageModuleTest; +import de.jplag.testutils.datacollector.TestDataCollector; +import de.jplag.testutils.datacollector.TestSourceIgnoredLinesCollector; + +public class JavaScriptLanguageTest extends LanguageModuleTest { + + public JavaScriptLanguageTest() { + super(new TypeScriptLanguage(), TypeScriptTokenType.class); + } + + @Override + protected void collectTestData(TestDataCollector collector) { + List javascriptTokens = new ArrayList<>(List.of(TypeScriptTokenType.values())); + javascriptTokens.removeAll(List.of(NAMESPACE_BEGIN, NAMESPACE_END, INTERFACE_BEGIN, INTERFACE_END, ENUM_BEGIN, ENUM_END, ENUM_MEMBER)); + collector.testFile("allJSTokens.js").testSourceCoverage().testContainedTokens(javascriptTokens.toArray(new TokenType[0])); + } + + @Override + protected void configureIgnoredLines(TestSourceIgnoredLinesCollector collector) { + collector.ignoreMultipleLines("/*", "*/"); + collector.ignoreLinesByPrefix("//"); + } +} diff --git a/languages/typescript/src/test/java/de/jplag/typescript/TypeScriptLanguageTest.java b/languages/typescript/src/test/java/de/jplag/typescript/TypeScriptLanguageTest.java new file mode 100644 index 000000000..338066bc7 --- /dev/null +++ b/languages/typescript/src/test/java/de/jplag/typescript/TypeScriptLanguageTest.java @@ -0,0 +1,46 @@ +package de.jplag.typescript; + +import de.jplag.testutils.LanguageModuleTest; +import de.jplag.testutils.datacollector.TestDataCollector; +import de.jplag.testutils.datacollector.TestSourceIgnoredLinesCollector; + +public class TypeScriptLanguageTest extends LanguageModuleTest { + + public TypeScriptLanguageTest() { + super(new TypeScriptLanguage(), TypeScriptTokenType.class); + } + + @Override + protected void collectTestData(TestDataCollector collector) { + collector.testFile("simpleTest.ts").testSourceCoverage().testTokenSequence(TypeScriptTokenType.DECLARATION, TypeScriptTokenType.ASSIGNMENT, + TypeScriptTokenType.DECLARATION, TypeScriptTokenType.ASSIGNMENT, TypeScriptTokenType.FOR_BEGIN, TypeScriptTokenType.ASSIGNMENT, + TypeScriptTokenType.ASSIGNMENT, TypeScriptTokenType.FUNCTION_CALL, TypeScriptTokenType.FOR_END, TypeScriptTokenType.DECLARATION, + TypeScriptTokenType.ASSIGNMENT, TypeScriptTokenType.FUNCTION_CALL, TypeScriptTokenType.ASSIGNMENT); + collector.testFile("forLoops.ts").testTokenSequence(TypeScriptTokenType.DECLARATION, TypeScriptTokenType.ASSIGNMENT, + TypeScriptTokenType.FOR_BEGIN, TypeScriptTokenType.ASSIGNMENT, TypeScriptTokenType.ASSIGNMENT, TypeScriptTokenType.FUNCTION_CALL, + TypeScriptTokenType.FOR_END, TypeScriptTokenType.FOR_BEGIN, TypeScriptTokenType.FUNCTION_CALL, TypeScriptTokenType.FOR_END, + TypeScriptTokenType.FOR_BEGIN, TypeScriptTokenType.FUNCTION_CALL, TypeScriptTokenType.FOR_END); + collector.testFile("methods.ts").testTokenSequence(TypeScriptTokenType.DECLARATION, TypeScriptTokenType.ASSIGNMENT, + TypeScriptTokenType.METHOD_BEGIN, TypeScriptTokenType.RETURN, TypeScriptTokenType.METHOD_END, TypeScriptTokenType.DECLARATION, + TypeScriptTokenType.ASSIGNMENT, TypeScriptTokenType.METHOD_BEGIN, TypeScriptTokenType.RETURN, TypeScriptTokenType.METHOD_END, + TypeScriptTokenType.DECLARATION, TypeScriptTokenType.ASSIGNMENT, TypeScriptTokenType.METHOD_BEGIN, TypeScriptTokenType.RETURN, + TypeScriptTokenType.METHOD_END); + collector.testFile("class.ts").testSourceCoverage().testTokenSequence(TypeScriptTokenType.CLASS_BEGIN, TypeScriptTokenType.DECLARATION, + TypeScriptTokenType.DECLARATION, TypeScriptTokenType.ASSIGNMENT, TypeScriptTokenType.CONSTRUCTOR_BEGIN, + TypeScriptTokenType.ASSIGNMENT, TypeScriptTokenType.CONSTRUCTOR_END, TypeScriptTokenType.METHOD_BEGIN, TypeScriptTokenType.RETURN, + TypeScriptTokenType.METHOD_END, TypeScriptTokenType.METHOD_BEGIN, TypeScriptTokenType.ASSIGNMENT, TypeScriptTokenType.METHOD_END, + TypeScriptTokenType.METHOD_BEGIN, TypeScriptTokenType.RETURN, TypeScriptTokenType.METHOD_END, TypeScriptTokenType.METHOD_BEGIN, + TypeScriptTokenType.ASSIGNMENT, TypeScriptTokenType.METHOD_END, TypeScriptTokenType.CLASS_END); + collector.testFile("if.ts").testSourceCoverage().testTokenSequence(TypeScriptTokenType.IF_BEGIN, TypeScriptTokenType.FUNCTION_CALL, + TypeScriptTokenType.IF_BEGIN, TypeScriptTokenType.IF_BEGIN, TypeScriptTokenType.FUNCTION_CALL, TypeScriptTokenType.IF_BEGIN, + TypeScriptTokenType.FUNCTION_CALL, TypeScriptTokenType.IF_END, TypeScriptTokenType.IF_END, TypeScriptTokenType.IF_BEGIN, + TypeScriptTokenType.FUNCTION_CALL, TypeScriptTokenType.IF_END); + collector.testFile("allTokens.ts").testCoverages(); + } + + @Override + protected void configureIgnoredLines(TestSourceIgnoredLinesCollector collector) { + collector.ignoreMultipleLines("/*", "*/"); + collector.ignoreLinesByPrefix("//"); + } +} diff --git a/languages/typescript/src/test/resources/de/jplag/typescript/allJSTokens.js b/languages/typescript/src/test/resources/de/jplag/typescript/allJSTokens.js new file mode 100644 index 000000000..315b9d965 --- /dev/null +++ b/languages/typescript/src/test/resources/de/jplag/typescript/allJSTokens.js @@ -0,0 +1,58 @@ +import {test} from 'test'; +class Class { + #x; + + constructor(x) { + this.x = x; + } + + test(y) { + return this.x + y; + } +} + +let a = 3; +const d = 4; + +function c() { + let b; + b = 8; + return a - b; +} + +switch (c()) { + case 1: + break; + default: + console.log(c()) +} + +try { + throw "Error" +} catch (e) { + console.log('Error', e); +} finally { + console.log() +} + +for (let i = 0; i < a; i++) { + +} + +while(a > 3) { + a--; + if (d > 5) { + continue; + } +} + +export default Class; +export { c }; + +if (d) { + +} else if (d < 10) { + +} else { + +} \ No newline at end of file diff --git a/languages/typescript/src/test/resources/de/jplag/typescript/allTokens.ts b/languages/typescript/src/test/resources/de/jplag/typescript/allTokens.ts new file mode 100644 index 000000000..86a64b99a --- /dev/null +++ b/languages/typescript/src/test/resources/de/jplag/typescript/allTokens.ts @@ -0,0 +1,70 @@ +import {test} from 'test'; + +namespace Name { + enum Values { + val1 = 3, + val2 + } +} + +interface Inter { + value: number; +} + +class Class { + private x; + + constructor(x) { + this.x = x; + } + + public test(y: number) { + return this.x + y; + } +} + +let a = 3; +const d = 4; + +function c() { + let b; + b = 8; + return a - b; +} + +switch (c()) { + case 1: + break; + default: + console.log(c()) +} + +try { + throw "Error" +} catch (e) { + console.log('Error', e); +} finally { + console.log() +} + +for (let i = 0; i < a; i++) { + +} + +while(a > 3) { + a--; + if (d > 5) { + continue; + } +} + +export default Name; +export { c }; + +if (d) { + +} else if (d < 10) { + +} else { + +} \ No newline at end of file diff --git a/languages/typescript/src/test/resources/de/jplag/typescript/class.ts b/languages/typescript/src/test/resources/de/jplag/typescript/class.ts new file mode 100644 index 000000000..fca08b0d6 --- /dev/null +++ b/languages/typescript/src/test/resources/de/jplag/typescript/class.ts @@ -0,0 +1,25 @@ +class AddTest { + + private _x: number; + protected _y = 5; + + constructor(x) { + this._x = x; + } + + public getX() { + return this._x; + } + + public setX(x: number) { + this._x = x; + } + + get y() { + return this._y; + } + + set y(y: number) { + this._y = y; + } +} \ No newline at end of file diff --git a/languages/typescript/src/test/resources/de/jplag/typescript/forLoops.ts b/languages/typescript/src/test/resources/de/jplag/typescript/forLoops.ts new file mode 100644 index 000000000..17c9b8a78 --- /dev/null +++ b/languages/typescript/src/test/resources/de/jplag/typescript/forLoops.ts @@ -0,0 +1,13 @@ +const are = ["Test", "Test2"]; + +for (let i = 0; i < are.length; i++) { + console.log(are[i]) +} + +for (const a in are) { + console.log(a) +} + +for (const a of are) { + console.log(a) +} \ No newline at end of file diff --git a/languages/typescript/src/test/resources/de/jplag/typescript/if.ts b/languages/typescript/src/test/resources/de/jplag/typescript/if.ts new file mode 100644 index 000000000..11c474542 --- /dev/null +++ b/languages/typescript/src/test/resources/de/jplag/typescript/if.ts @@ -0,0 +1,11 @@ +if (true) { + console.log() +} else if(true) { + console.log() +} else { + console.log() +} + +if (true) { + console.log() +} \ No newline at end of file diff --git a/languages/typescript/src/test/resources/de/jplag/typescript/methods.ts b/languages/typescript/src/test/resources/de/jplag/typescript/methods.ts new file mode 100644 index 000000000..69cf57521 --- /dev/null +++ b/languages/typescript/src/test/resources/de/jplag/typescript/methods.ts @@ -0,0 +1,11 @@ +function add1(a: number, b: number) { + return a + b; +} + +const add2 = function (a: number, b: number) { + return a + b; +} + +const add3 = (a: number, b: number) => { + return a + b; +} \ No newline at end of file diff --git a/languages/typescript/src/test/resources/de/jplag/typescript/simpleTest.ts b/languages/typescript/src/test/resources/de/jplag/typescript/simpleTest.ts new file mode 100644 index 000000000..9f57d346d --- /dev/null +++ b/languages/typescript/src/test/resources/de/jplag/typescript/simpleTest.ts @@ -0,0 +1,9 @@ +let counter = 0; +let arr = [] + +for (let i = 1; i <=5; i++) { + arr.push(i); +} + +let arrRev = arr.reverse(); +counter++; \ No newline at end of file diff --git a/pom.xml b/pom.xml index 07d4e5ad0..a478a9fbe 100644 --- a/pom.xml +++ b/pom.xml @@ -74,18 +74,19 @@ 17 17 - 2.35.0 - 2.0.7 - 5.9.2 + 2.40.0 + 2.0.9 + 5.10.0 2.7.7 - 4.12.0 - 2.33.0 - 2.28.0 - 2.18.0 + 4.13.1 + 2.35.0 + 2.29.0 + 2.35.0 + 1.0.0 - 4.3.0 + 4.4.0-SNAPSHOT @@ -116,7 +117,7 @@ edu.stanford.nlp stanford-corenlp - 4.5.3 + 4.5.5 @@ -133,13 +134,13 @@ org.kohsuke.metainf-services metainf-services - 1.9 + 1.11 com.fasterxml.jackson.core jackson-databind - 2.14.2 + 2.15.3
@@ -166,7 +167,7 @@ org.mockito mockito-core - 5.2.0 + 5.6.0 test @@ -222,7 +223,7 @@ org.apache.maven.plugins maven-assembly-plugin - 3.5.0 + 3.6.0 jar-with-dependencies @@ -238,12 +239,12 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0 + 3.1.2 org.jacoco jacoco-maven-plugin - 0.8.8 + 0.8.11 prepare-agent @@ -267,12 +268,12 @@ org.apache.maven.plugins maven-gpg-plugin - 3.0.1 + 3.1.0 org.apache.maven.plugins maven-deploy-plugin - 3.1.0 + 3.1.1 @@ -280,7 +281,7 @@ org.codehaus.mojo flatten-maven-plugin - 1.4.0 + 1.5.0 true resolveCiFriendliesOnly @@ -309,7 +310,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.3.0 + 3.4.0 add-source @@ -329,7 +330,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.5.0 + 3.6.0 attach-javadocs @@ -342,7 +343,7 @@ org.apache.maven.plugins maven-source-plugin - 3.2.1 + 3.3.0 attach-sources @@ -408,6 +409,7 @@ endtoend-testing languages language-api + language-antlr-utils language-testutils diff --git a/report-viewer/.browserslistrc b/report-viewer/.browserslistrc deleted file mode 100644 index 214388fe4..000000000 --- a/report-viewer/.browserslistrc +++ /dev/null @@ -1,3 +0,0 @@ -> 1% -last 2 versions -not dead diff --git a/report-viewer/.eslintrc.cjs b/report-viewer/.eslintrc.cjs new file mode 100644 index 000000000..1d62fdec6 --- /dev/null +++ b/report-viewer/.eslintrc.cjs @@ -0,0 +1,35 @@ +/* eslint-env node */ +require('@rushstack/eslint-patch/modern-module-resolution') + +module.exports = { + root: true, + extends: [ + 'plugin:vue/vue3-essential', + 'eslint:recommended', + '@vue/eslint-config-typescript', + '@vue/eslint-config-prettier/skip-formatting' + ], + parserOptions: { + ecmaVersion: 'latest' + }, + plugins: ['@typescript-eslint', 'vue'], + rules: { + "no-console": process.env.NODE_ENV === "production" ? "warn" : "off", + "no-restricted-exports": ['error', { 'restrictDefaultExports': { 'direct': true } }], + "vue/no-setup-props-reactivity-loss": "error" + }, + overrides: [ + { + files: ['*.config.ts', '*.config.js', '*.d.ts'], + rules: { + "no-restricted-exports": "off" + } + }, + { + files: ['*.html'], + rules: { + 'vue/comment-directive': 'off' + } + } + ] +} diff --git a/report-viewer/.eslintrc.js b/report-viewer/.eslintrc.js deleted file mode 100644 index 0cebcaafa..000000000 --- a/report-viewer/.eslintrc.js +++ /dev/null @@ -1,20 +0,0 @@ -module.exports = { - root: true, - env: { - node: true, - }, - extends: [ - "plugin:vue/vue3-essential", - "eslint:recommended", - "@vue/typescript/recommended", - "@vue/prettier", - ], - parserOptions: { - ecmaVersion: 2020, - }, - rules: { - "no-console": process.env.NODE_ENV === "production" ? "warn" : "off", - "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off", - 'prettier/prettier': 0, - }, -}; diff --git a/report-viewer/.gitignore b/report-viewer/.gitignore index 403adbc1e..719bf30c1 100644 --- a/report-viewer/.gitignore +++ b/report-viewer/.gitignore @@ -1,23 +1,31 @@ -.DS_Store -node_modules -/dist - - -# local env files -.env.local -.env.*.local - -# Log files +# Logs +logs +*.log npm-debug.log* yarn-debug.log* yarn-error.log* pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ # Editor directories and files +.vscode/* +!.vscode/extensions.json .idea -.vscode *.suo *.ntvs* *.njsproj *.sln *.sw? + +test-results/ +playwright-report/ diff --git a/report-viewer/.husky/pre-commit b/report-viewer/.husky/pre-commit new file mode 100644 index 000000000..b93aca0a8 --- /dev/null +++ b/report-viewer/.husky/pre-commit @@ -0,0 +1,5 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +cd ./report-viewer +npx lint-staged diff --git a/report-viewer/.lintstagedrc.json b/report-viewer/.lintstagedrc.json new file mode 100644 index 000000000..5c5cdfd30 --- /dev/null +++ b/report-viewer/.lintstagedrc.json @@ -0,0 +1,7 @@ +{ + "*.ts": ["npx prettier --write", "npx eslint"], + "*.vue": ["npx prettier --write", "npx eslint"], + "*.js": ["npx prettier --write", "npx eslint"], + "*.html": ["npx prettier --write", "npx eslint"], + "*.css": ["npx prettier --write"] +} diff --git a/report-viewer/.prettierignore b/report-viewer/.prettierignore new file mode 100644 index 000000000..2e1fa2d52 --- /dev/null +++ b/report-viewer/.prettierignore @@ -0,0 +1 @@ +*.md \ No newline at end of file diff --git a/report-viewer/.prettierrc.json b/report-viewer/.prettierrc.json new file mode 100644 index 000000000..15c88de8e --- /dev/null +++ b/report-viewer/.prettierrc.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://json.schemastore.org/prettierrc", + "semi": false, + "tabWidth": 2, + "singleQuote": true, + "printWidth": 100, + "trailingComma": "none", + "endOfLine": "auto", + "plugins": ["prettier-plugin-tailwindcss"] +} diff --git a/report-viewer/README.md b/report-viewer/README.md index 30c0a3fac..c39bf4f8e 100644 --- a/report-viewer/README.md +++ b/report-viewer/README.md @@ -5,8 +5,8 @@ The JPlag Report Viewer is a Vue 3 + Typescript standalone application that can Before the first run execute: - Install necessary dependencies by running `npm install` in the /report-viewer folder. -- Start the application by running the `npm run serve` command in the /report-viewer folder. -- The report viewer is now accessible in your browser under http://localhost:8080/JPlag/ +- Start the application by running the `npm run dev` command in the /report-viewer folder. +- The report viewer is now accessible in your browser under http://localhost:8080/ ## Project setup ``` @@ -15,7 +15,7 @@ npm install ### Compiles and hot-reloads for development ``` -npm run serve +npm run dev ``` ### Compiles and minifies for production @@ -28,5 +28,10 @@ npm run build npm run lint ``` +### Format files with prettier +``` +npm run format +``` + ### Customize configuration See [Configuration Reference](https://cli.vuejs.org/config/). diff --git a/report-viewer/babel.config.js b/report-viewer/babel.config.js deleted file mode 100644 index 162a3ea97..000000000 --- a/report-viewer/babel.config.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - presets: ["@vue/cli-plugin-babel/preset"], -}; diff --git a/report-viewer/env.d.ts b/report-viewer/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/report-viewer/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/report-viewer/index.html b/report-viewer/index.html new file mode 100644 index 000000000..f4fedd2bd --- /dev/null +++ b/report-viewer/index.html @@ -0,0 +1,19 @@ + + + + + + + JPlag Report Viewer + + + +
+ + + diff --git a/report-viewer/jest.config.js b/report-viewer/jest.config.js deleted file mode 100644 index 2debbc330..000000000 --- a/report-viewer/jest.config.js +++ /dev/null @@ -1,17 +0,0 @@ -module.exports = { - preset: 'ts-jest', - globals: {}, - testEnvironment: 'jsdom', - transform: { - "^.+\\.vue$": "@vue/vue3-jest", - "^.+\\js$": "babel-jest", - "^.+\\.(css|scss|png|jpg|svg)$": "jest-transform-stub" - }, - moduleFileExtensions: ['vue', 'js', 'json', 'jsx', 'ts', 'tsx', 'node'], - moduleNameMapper: { - '^@/(.*)$': '/src/$1' - }, - testEnvironmentOptions: { - customExportConditions: ["node", "node-addons"], - } -} \ No newline at end of file diff --git a/report-viewer/package-lock.json b/report-viewer/package-lock.json index c3dd9811c..baf08f907 100644 --- a/report-viewer/package-lock.json +++ b/report-viewer/package-lock.json @@ -1,2022 +1,1903 @@ { "name": "report-viewer", - "version": "0.1.0", - "lockfileVersion": 2, + "version": "0.0.0", + "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "report-viewer", - "version": "0.1.0", + "version": "0.0.0", "dependencies": { - "@highlightjs/vue-plugin": "^2.1.0", - "chart.js": "^3.9.1", + "@fortawesome/fontawesome-svg-core": "^6.4.2", + "@fortawesome/free-regular-svg-icons": "^6.4.2", + "@fortawesome/free-solid-svg-icons": "^6.4.2", + "@fortawesome/vue-fontawesome": "^3.0.3", + "chart.js": "^4.4.0", "chartjs-plugin-datalabels": "^2.2.0", - "core-js": "^3.29.1", - "gitart-vue-dialog": "^2.4.1", - "highlight.js": "^11.7.0", + "highlight.js": "^11.9.0", "jszip": "^3.10.0", - "node-polyfill-webpack-plugin": "^2.0.0", - "slash": "^5.0.0", - "vue": "^3.2.47", - "vue-chart-3": "^3.1.8", - "vue-draggable-next": "^2.1.1", - "vue-router": "^4.1.6", - "vue-virtual-scroller": "^2.0.0-beta.8", - "vue3-highlightjs": "^1.0.5", - "vuex": "^4.0.2" + "pinia": "^2.1.7", + "slash": "^5.1.0", + "vue": "^3.3.4", + "vue-chartjs": "^5.2.0", + "vue-draggable-next": "^2.2.1", + "vue-router": "^4.2.5", + "vue-virtual-scroller": "^2.0.0-beta.8" }, "devDependencies": { - "@types/jest": "^29.5.0", - "@typescript-eslint/eslint-plugin": "^5.56.0", - "@typescript-eslint/parser": "^5.55.0", - "@vue/cli-plugin-babel": "~5.0.8", - "@vue/cli-plugin-eslint": "~5.0.8", - "@vue/cli-plugin-router": "~5.0.8", - "@vue/cli-plugin-typescript": "~5.0.8", - "@vue/cli-service": "~5.0.8", - "@vue/compiler-sfc": "^3.2.39", - "@vue/eslint-config-prettier": "^7.0.0", - "@vue/eslint-config-typescript": "^10.0.0", - "@vue/test-utils": "^2.3.2", - "@vue/vue3-jest": "^29.2.3", - "eslint": "^8.35.0", - "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-vue": "^8.7.1", - "jest": "^29.5.0", - "jest-environment-jsdom": "^29.5.0", - "jest-transform-stub": "^2.0.0", - "lint-staged": "^13.2.0", - "prettier": "^2.8.6", - "ts-jest": "^29.0.5", - "typescript": "~5.0.2" - } - }, - "node_modules/@achrinza/node-ipc": { - "version": "9.2.5", - "resolved": "https://registry.npmjs.org/@achrinza/node-ipc/-/node-ipc-9.2.5.tgz", - "integrity": "sha512-kBX7Ay911iXZ3VZ1pYltj3Rfu7Ow9H7sK4H4RSfWIfWR2JKNB40K808wppoRIEzE2j2hXLU+r6TJgCAliCGhyQ==", - "dev": true, - "dependencies": { - "@node-ipc/js-queue": "2.0.3", - "event-pubsub": "4.3.0", - "js-message": "1.0.7" - }, - "engines": { - "node": "8 || 9 || 10 || 11 || 12 || 13 || 14 || 15 || 16 || 17 || 18" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", - "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.6.tgz", - "integrity": "sha512-tzulrgDT0QD6U7BJ4TKVk2SDDg7wlP39P9yAx1RfLy7vP/7rsDRlWVfbWxElslu56+r7QOhB2NSDsabYYruoZQ==", + "@playwright/test": "^1.38.1", + "@rushstack/eslint-patch": "^1.5.1", + "@types/jsdom": "^21.1.3", + "@types/node": "^18.18.6", + "@vitejs/plugin-vue": "^4.4.0", + "@vue/eslint-config-prettier": "^8.0.0", + "@vue/eslint-config-typescript": "^12.0.0", + "@vue/test-utils": "^2.4.1", + "@vue/tsconfig": "^0.4.0", + "autoprefixer": "^10.4.15", + "eslint": "^8.51.0", + "eslint-plugin-vue": "^9.17.0", + "husky": "^8.0.0", + "jsdom": "^22.1.0", + "lint-staged": "^15.0.1", + "npm-run-all": "^4.1.5", + "postcss": "^8.4.31", + "prettier": "^3.0.3", + "prettier-plugin-tailwindcss": "^0.5.6", + "tailwindcss": "^3.3.3", + "typescript": "^5.2.2", + "vite": "^4.5.0", + "vitest": "^0.34.6", + "vue-tsc": "^1.8.15" + } + }, + "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, "engines": { - "node": ">=6.9.0" + "node": ">=0.10.0" } }, - "node_modules/@babel/core": { - "version": "7.17.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.5.tgz", - "integrity": "sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA==", + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.3", - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helpers": "^7.17.2", - "@babel/parser": "^7.17.3", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0" - }, "engines": { - "node": ">=6.9.0" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@babel/generator": { - "version": "7.18.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.7.tgz", - "integrity": "sha512-shck+7VLlY72a2w9c3zYWuE1pwOKEiQHV7GTUbSnhyl5eu3i04t30tBY82ZRWrDfo3gkakCFtevExnxbkf2a3A==", - "dev": true, - "dependencies": { - "@babel/types": "^7.18.7", - "@jridgewell/gen-mapping": "^0.3.2", - "jsesc": "^2.5.1" + "node_modules/@babel/parser": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", + "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==", + "bin": { + "parser": "bin/babel-parser.js" }, "engines": { - "node": ">=6.9.0" + "node": ">=6.0.0" } }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", - "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "node_modules/@esbuild/android-arm": { + "version": "0.18.14", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.14.tgz", + "integrity": "sha512-blODaaL+lngG5bdK/t4qZcQvq2BBqrABmYwqPPcS5VRxrCSGHb9R/rA3fqxh7R18I7WU4KKv+NYkt22FDfalcg==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.6.tgz", - "integrity": "sha512-KT10c1oWEpmrIRYnthbzHgoOf6B+Xd6a5yhdbNtdhtG7aO1or5HViuf1TQR36xY/QprXA5nvxO6nAjhJ4y38jw==", + "node_modules/@esbuild/android-arm64": { + "version": "0.18.14", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.14.tgz", + "integrity": "sha512-rZ2v+Luba5/3D6l8kofWgTnqE+qsC/L5MleKIKFyllHTKHrNBMqeRCnZI1BtRx8B24xMYxeU32iIddRQqMsOsg==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-explode-assignable-expression": "^7.18.6", - "@babel/types": "^7.18.6" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.6.tgz", - "integrity": "sha512-vFjbfhNCzqdeAtZflUFrG5YIFqGTqsctrtkZ1D/NB0mDW9TwW3GmmUepYY4G9wCET5rY5ugz4OGTcLd614IzQg==", + "node_modules/@esbuild/android-x64": { + "version": "0.18.14", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.14.tgz", + "integrity": "sha512-qSwh8y38QKl+1Iqg+YhvCVYlSk3dVLk9N88VO71U4FUjtiSFylMWK3Ugr8GC6eTkkP4Tc83dVppt2n8vIdlSGg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/compat-data": "^7.18.6", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.20.2", - "semver": "^6.3.0" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=12" } }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.6.tgz", - "integrity": "sha512-YfDzdnoxHGV8CzqHGyCbFvXg5QESPFkXlHtvdCkesLjjVMT2Adxe4FGUR5ChIb3DxSaXO12iIOCWoXdsUVwnqw==", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.18.14", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.14.tgz", + "integrity": "sha512-9Hl2D2PBeDYZiNbnRKRWuxwHa9v5ssWBBjisXFkVcSP5cZqzZRFBUWEQuqBHO4+PKx4q4wgHoWtfQ1S7rUqJ2Q==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.6", - "@babel/helper-function-name": "^7.18.6", - "@babel/helper-member-expression-to-functions": "^7.18.6", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=12" } }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.18.6.tgz", - "integrity": "sha512-7LcpH1wnQLGrI+4v+nPp+zUvIkF9x0ddv1Hkdue10tg3gmRnLy97DXh4STiOf1qeIInyD69Qv5kKSZzKD8B/7A==", + "node_modules/@esbuild/darwin-x64": { + "version": "0.18.14", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.14.tgz", + "integrity": "sha512-ZnI3Dg4ElQ6tlv82qLc/UNHtFsgZSKZ7KjsUNAo1BF1SoYDjkGKHJyCrYyWjFecmXpvvG/KJ9A/oe0H12odPLQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "regexpu-core": "^5.1.0" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz", - "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.13.0", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/traverse": "^7.13.0", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0-0" + "node": ">=12" } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.6.tgz", - "integrity": "sha512-8n6gSfn2baOY+qlp+VSzsosjCVGFqWKmDF0cCWOybh52Dw3SEyoWR1KrhMJASjLwIEkkAufZ0xvr+SxLHSpy2Q==", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.14", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.14.tgz", + "integrity": "sha512-h3OqR80Da4oQCIa37zl8tU5MwHQ7qgPV0oVScPfKJK21fSRZEhLE4IIVpmcOxfAVmqjU6NDxcxhYaM8aDIGRLw==", + "cpu": [ + "arm64" + ], "dev": true, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-explode-assignable-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", - "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.18.14", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.14.tgz", + "integrity": "sha512-ha4BX+S6CZG4BoH9tOZTrFIYC1DH13UTCRHzFc3GWX74nz3h/N6MPF3tuR3XlsNjMFUazGgm35MPW5tHkn2lzQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-function-name": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.6.tgz", - "integrity": "sha512-0mWMxV1aC97dhjCah5U5Ua7668r5ZmSC2DLfH2EZnf9c3/dHZKiFa5pRLMH5tjSl471tY6496ZWk/kjNONBxhw==", + "node_modules/@esbuild/linux-arm": { + "version": "0.18.14", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.14.tgz", + "integrity": "sha512-5+7vehI1iqru5WRtJyU2XvTOvTGURw3OZxe3YTdE9muNNIdmKAVmSHpB3Vw2LazJk2ifEdIMt/wTWnVe5V98Kg==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@babel/template": "^7.18.6", - "@babel/types": "^7.18.6" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "node_modules/@esbuild/linux-arm64": { + "version": "0.18.14", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.14.tgz", + "integrity": "sha512-IXORRe22In7U65NZCzjwAUc03nn8SDIzWCnfzJ6t/8AvGx5zBkcLfknI+0P+hhuftufJBmIXxdSTbzWc8X/V4w==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.6.tgz", - "integrity": "sha512-CeHxqwwipekotzPDUuJOfIMtcIHBuc7WAzLmTYWctVigqS5RktNMQ5bEwQSuGewzYnCtTWa3BARXeiLxDTv+Ng==", + "node_modules/@esbuild/linux-ia32": { + "version": "0.18.14", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.14.tgz", + "integrity": "sha512-BfHlMa0nibwpjG+VXbOoqJDmFde4UK2gnW351SQ2Zd4t1N3zNdmUEqRkw/srC1Sa1DRBE88Dbwg4JgWCbNz/FQ==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "node_modules/@esbuild/linux-loong64": { + "version": "0.18.14", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.14.tgz", + "integrity": "sha512-j2/Ex++DRUWIAaUDprXd3JevzGtZ4/d7VKz+AYDoHZ3HjJzCyYBub9CU1wwIXN+viOP0b4VR3RhGClsvyt/xSw==", + "cpu": [ + "loong64" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.6.tgz", - "integrity": "sha512-L//phhB4al5uucwzlimruukHB3jRd5JGClwRMD/ROrVjXfLqovYnvQrK/JK36WYyVwGGO7OD3kMyVTjx+WVPhw==", + "node_modules/@esbuild/linux-mips64el": { + "version": "0.18.14", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.14.tgz", + "integrity": "sha512-qn2+nc+ZCrJmiicoAnJXJJkZWt8Nwswgu1crY7N+PBR8ChBHh89XRxj38UU6Dkthl2yCVO9jWuafZ24muzDC/A==", + "cpu": [ + "mips64el" + ], "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.18.6", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.18.6", - "@babel/template": "^7.18.6", - "@babel/traverse": "^7.18.6", - "@babel/types": "^7.18.6" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", - "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.18.14", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.14.tgz", + "integrity": "sha512-aGzXzd+djqeEC5IRkDKt3kWzvXoXC6K6GyYKxd+wsFJ2VQYnOWE954qV2tvy5/aaNrmgPTb52cSCHFE+Z7Z0yg==", + "cpu": [ + "ppc64" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.18.14", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.14.tgz", + "integrity": "sha512-8C6vWbfr0ygbAiMFLS6OPz0BHvApkT2gCboOGV76YrYw+sD/MQJzyITNsjZWDXJwPu9tjrFQOVG7zijRzBCnLw==", + "cpu": [ + "riscv64" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.6.tgz", - "integrity": "sha512-z5wbmV55TveUPZlCLZvxWHtrjuJd+8inFhk7DG0WW87/oJuGDcjDiu7HIvGcpf5464L6xKCg3vNkmlVVz9hwyQ==", + "node_modules/@esbuild/linux-s390x": { + "version": "0.18.14", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.14.tgz", + "integrity": "sha512-G/Lf9iu8sRMM60OVGOh94ZW2nIStksEcITkXdkD09/T6QFD/o+g0+9WVyR/jajIb3A0LvBJ670tBnGe1GgXMgw==", + "cpu": [ + "s390x" + ], "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.6", - "@babel/helper-wrap-function": "^7.18.6", - "@babel/types": "^7.18.6" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=12" } }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.6.tgz", - "integrity": "sha512-fTf7zoXnUGl9gF25fXCWE26t7Tvtyn6H4hkLSYhATwJvw2uYxd3aoXplMSe0g9XbwK7bmxNes7+FGO0rB/xC0g==", + "node_modules/@esbuild/linux-x64": { + "version": "0.18.14", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.14.tgz", + "integrity": "sha512-TBgStYBQaa3EGhgqIDM+ECnkreb0wkcKqL7H6m+XPcGUoU4dO7dqewfbm0mWEQYH3kzFHrzjOFNpSAVzDZRSJw==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.18.6", - "@babel/helper-member-expression-to-functions": "^7.18.6", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/traverse": "^7.18.6", - "@babel/types": "^7.18.6" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", - "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.18.14", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.14.tgz", + "integrity": "sha512-stvCcjyCQR2lMTroqNhAbvROqRjxPEq0oQ380YdXxA81TaRJEucH/PzJ/qsEtsHgXlWFW6Ryr/X15vxQiyRXVg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.6.tgz", - "integrity": "sha512-4KoLhwGS9vGethZpAhYnMejWkX64wsnHPDwvOsKWU6Fg4+AlK2Jz3TyjQLMEPvz+1zemi/WBdkYxCD0bAfIkiw==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.18.14", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.14.tgz", + "integrity": "sha512-apAOJF14CIsN5ht1PA57PboEMsNV70j3FUdxLmA2liZ20gEQnfTG5QU0FhENo5nwbTqCB2O3WDsXAihfODjHYw==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "node_modules/@esbuild/sunos-x64": { + "version": "0.18.14", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.14.tgz", + "integrity": "sha512-fYRaaS8mDgZcGybPn2MQbn1ZNZx+UXFSUoS5Hd2oEnlsyUcr/l3c6RnXf1bLDRKKdLRSabTmyCy7VLQ7VhGdOQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "node_modules/@esbuild/win32-arm64": { + "version": "0.18.14", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.14.tgz", + "integrity": "sha512-1c44RcxKEJPrVj62XdmYhxXaU/V7auELCmnD+Ri+UCt+AGxTvzxl9uauQhrFso8gj6ZV1DaORV0sT9XSHOAk8Q==", + "cpu": [ + "arm64" + ], "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "node_modules/@esbuild/win32-ia32": { + "version": "0.18.14", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.14.tgz", + "integrity": "sha512-EXAFttrdAxZkFQmpvcAQ2bywlWUsONp/9c2lcfvPUhu8vXBBenCXpoq9YkUvVP639ld3YGiYx0YUQ6/VQz3Maw==", + "cpu": [ + "ia32" + ], "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-validator-option": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "node_modules/@esbuild/win32-x64": { + "version": "0.18.14", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.14.tgz", + "integrity": "sha512-K0QjGbcskx+gY+qp3v4/940qg8JitpXbdxFhRDA1aYoNaPff88+aEwoq45aqJ+ogpxQxmU0ZTjgnrQD/w8iiUg==", + "cpu": [ + "x64" + ], "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.18.6.tgz", - "integrity": "sha512-I5/LZfozwMNbwr/b1vhhuYD+J/mU+gfGAj5td7l5Rv9WYmH6i3Om69WGKNmlIpsVW/mF6O5bvTKbvDQZVgjqOw==", + "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, "dependencies": { - "@babel/helper-function-name": "^7.18.6", - "@babel/template": "^7.18.6", - "@babel/traverse": "^7.18.6", - "@babel/types": "^7.18.6" + "eslint-visitor-keys": "^3.3.0" }, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@babel/helpers": { - "version": "7.17.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.2.tgz", - "integrity": "sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ==", + "node_modules/@eslint-community/regexpp": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.7.0.tgz", + "integrity": "sha512-+HencqxU7CFJnQb7IKtuNBqS6Yx3Tz4kOL8BJXo+JyeiBm5MEX6pO8onXDkjrkCRlfYXS1Axro15ZjVFe9YgsA==", "dev": true, - "dependencies": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.0", - "@babel/types": "^7.17.0" - }, "engines": { - "node": ">=6.9.0" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "node_modules/@eslint/eslintrc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@babel/parser": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.7.tgz", - "integrity": "sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==", - "bin": { - "parser": "bin/babel-parser.js" - }, + "node_modules/@eslint/js": { + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz", + "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==", + "dev": true, "engines": { - "node": ">=6.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz", - "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, + "node_modules/@fortawesome/fontawesome-common-types": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.2.tgz", + "integrity": "sha512-1DgP7f+XQIJbLFCTX1V2QnxVmpLdKdzzo2k8EmvDOePfchaIGQ9eCHj2up3/jNEbZuBqel5OxiaOJf37TWauRA==", + "hasInstallScript": true, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=6" } }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.6.tgz", - "integrity": "sha512-Udgu8ZRgrBrttVz6A0EVL0SJ1z+RLbIeqsu632SA1hf0awEppD6TvdznoH+orIF8wtFFAV/Enmw9Y+9oV8TQcw==", - "dev": true, + "node_modules/@fortawesome/fontawesome-svg-core": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.2.tgz", + "integrity": "sha512-gjYDSKv3TrM2sLTOKBc5rH9ckje8Wrwgx1CxAPbN5N3Fm4prfi7NsJVWd1jklp7i5uSCVwhZS5qlhMXqLrpAIg==", + "hasInstallScript": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.6", - "@babel/plugin-proposal-optional-chaining": "^7.18.6" + "@fortawesome/fontawesome-common-types": "6.4.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.13.0" + "node": ">=6" } }, - "node_modules/@babel/plugin-proposal-async-generator-functions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.6.tgz", - "integrity": "sha512-WAz4R9bvozx4qwf74M+sfqPMKfSqwM0phxPTR6iJIi8robgzXwkEgmeJG1gEKhm6sDqT/U9aV3lfcqybIpev8w==", - "dev": true, + "node_modules/@fortawesome/free-regular-svg-icons": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.4.2.tgz", + "integrity": "sha512-0+sIUWnkgTVVXVAPQmW4vxb9ZTHv0WstOa3rBx9iPxrrrDH6bNLsDYuwXF9b6fGm+iR7DKQvQshUH/FJm3ed9Q==", + "hasInstallScript": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-remap-async-to-generator": "^7.18.6", - "@babel/plugin-syntax-async-generators": "^7.8.4" + "@fortawesome/fontawesome-common-types": "6.4.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=6" } }, - "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "dev": true, + "node_modules/@fortawesome/free-solid-svg-icons": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.2.tgz", + "integrity": "sha512-sYwXurXUEQS32fZz9hVCUUv/xu49PEJEyUOsA51l6PU/qVgfbTb2glsTEaJngVVT8VqBATRIdh7XVgV1JF1LkA==", + "hasInstallScript": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@fortawesome/fontawesome-common-types": "6.4.2" }, "engines": { - "node": ">=6.9.0" - }, + "node": ">=6" + } + }, + "node_modules/@fortawesome/vue-fontawesome": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-3.0.3.tgz", + "integrity": "sha512-KCPHi9QemVXGMrfuwf3nNnNo129resAIQWut9QTAMXmXqL2ErABC6ohd2yY5Ipq0CLWNbKHk8TMdTXL/Zf3ZhA==", "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@fortawesome/fontawesome-svg-core": "~1 || ~6", + "vue": ">= 3.0.0 < 4" } }, - "node_modules/@babel/plugin-proposal-class-static-block": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz", - "integrity": "sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==", + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", + "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-class-static-block": "^7.14.5" + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" + "node": ">=10.10.0" } }, - "node_modules/@babel/plugin-proposal-decorators": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.18.6.tgz", - "integrity": "sha512-gAdhsjaYmiZVxx5vTMiRfj31nB7LhwBJFMSLzeDxc7X4tKLixup0+k9ughn0RcpBrv9E3PBaXJW7jF5TCihAOg==", + "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, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/plugin-syntax-decorators": "^7.18.6" - }, "engines": { - "node": ">=6.9.0" + "node": ">=12.22" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@babel/plugin-proposal-dynamic-import": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", - "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true }, - "node_modules/@babel/plugin-proposal-export-namespace-from": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.6.tgz", - "integrity": "sha512-zr/QcUlUo7GPo6+X1wC98NJADqmy5QTFWWhqeQWiki4XHafJtLl/YMGkmRB2szDD2IYJCCdBTd4ElwhId9T7Xw==", + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@babel/plugin-proposal-json-strings": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", - "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-json-strings": "^7.8.3" + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.6.tgz", - "integrity": "sha512-zMo66azZth/0tVd7gmkxOkOjs2rpHyhpcFo565PUP37hSp6hSd9uUKIfTDFMz58BwqgQKhJ9YxtM5XddjXVn+Q==", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", - "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-proposal-numeric-separator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", - "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", + "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" } }, - "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.6.tgz", - "integrity": "sha512-9yuM6wr4rIsKa1wlUAbZEazkCrgw2sMPEXCr4Rnwetu7cEW1NydkCWytLuYletbf8vFxdJxFhwEZqMpOx2eZyw==", + "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@kurkle/color": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", + "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.18.6", - "@babel/helper-compilation-targets": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.18.6" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 8" } }, - "node_modules/@babel/plugin-proposal-optional-catch-binding": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", - "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", + "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, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 8" } }, - "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.6.tgz", - "integrity": "sha512-PatI6elL5eMzoypFAiYDpYQyMtXTn+iMhuxxQt5mAXD4fEmKorpSI3PHd+i3JXBJN3xyA6MvJv7at23HffFHwA==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.6", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 8" } }, - "node_modules/@babel/plugin-proposal-private-methods": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", - "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "node_modules/@one-ini/wasm": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", + "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==", + "dev": true + }, + "node_modules/@pkgr/utils": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz", + "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "cross-spawn": "^7.0.3", + "fast-glob": "^3.3.0", + "is-glob": "^4.0.3", + "open": "^9.1.0", + "picocolors": "^1.0.0", + "tslib": "^2.6.0" }, "engines": { - "node": ">=6.9.0" + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://opencollective.com/unts" } }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz", - "integrity": "sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==", + "node_modules/@pkgr/utils/node_modules/tslib": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", + "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==", + "dev": true + }, + "node_modules/@playwright/test": { + "version": "1.38.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.38.1.tgz", + "integrity": "sha512-NqRp8XMwj3AK+zKLbZShl0r/9wKgzqI/527bkptKXomtuo+dOjU9NdMASQ8DNC9z9zLOMbG53T4eihYr3XR+BQ==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + "playwright": "1.38.1" }, - "engines": { - "node": ">=6.9.0" + "bin": { + "playwright": "cli.js" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=16" } }, - "node_modules/@babel/plugin-proposal-unicode-property-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", - "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", + "node_modules/@rushstack/eslint-patch": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.5.1.tgz", + "integrity": "sha512-6i/8UoL0P5y4leBIGzvkZdS85RDMG9y1ihZzmTZQ5LdHUYmZ7pKFoj8X0236s3lusPs1Fa5HTQUpwI+UfTcmeA==", + "dev": true + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, "engines": { - "node": ">=4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 10" } }, - "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==", + "node_modules/@types/chai": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz", + "integrity": "sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==", + "dev": true + }, + "node_modules/@types/chai-subset": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.3.tgz", + "integrity": "sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@types/chai": "*" } }, - "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==", + "node_modules/@types/jsdom": { + "version": "21.1.3", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.3.tgz", + "integrity": "sha512-1zzqSP+iHJYV4lB3lZhNBa012pubABkj9yG/GuXuf6LZH1cSPIJBqFDrm5JX65HHt6VOnNYdTui/0ySerRbMgA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@types/node": "*", + "@types/tough-cookie": "*", + "parse5": "^7.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==", + "node_modules/@types/json-schema": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz", + "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.18.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.6.tgz", + "integrity": "sha512-wf3Vz+jCmOQ2HV1YUJuCWdL64adYxumkrxtc+H1VUQlnQI04+5HtH+qZCOE21lBE7gIrt+CwX2Wv8Acrw5Ak6w==", + "dev": true + }, + "node_modules/@types/semver": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==", + "dev": true + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz", + "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.5.tgz", + "integrity": "sha512-JhtAwTRhOUcP96D0Y6KYnwig/MRQbOoLGXTON2+LlyB/N35SP9j1boai2zzwXb7ypKELXMx3DVk9UTaEq1vHEw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.7.5", + "@typescript-eslint/type-utils": "6.7.5", + "@typescript-eslint/utils": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "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==", + "node_modules/@typescript-eslint/parser": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.5.tgz", + "integrity": "sha512-bIZVSGx2UME/lmhLcjdVc7ePBwn7CLqKarUBL4me1C5feOd663liTGjMBGVcGr+BhnSLeP4SgwdvNnnkbIdkCw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@typescript-eslint/scope-manager": "6.7.5", + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/typescript-estree": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", + "debug": "^4.3.4" }, "engines": { - "node": ">=6.9.0" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@babel/plugin-syntax-decorators": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.18.6.tgz", - "integrity": "sha512-fqyLgjcxf/1yhyZ6A+yo1u9gJ7eleFQod2lkaUsF9DQ7sbbY3Ligym3L0+I2c0WmqNKDpoD9UTb1AKP3qRMOAQ==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.5.tgz", + "integrity": "sha512-GAlk3eQIwWOJeb9F7MKQ6Jbah/vx1zETSDw8likab/eFcqkjSD7BI75SDAeC5N2L0MmConMoPvTsmkrg71+B1A==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5" }, "engines": { - "node": ">=6.9.0" + "node": "^16.0.0 || >=18.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "node_modules/@typescript-eslint/type-utils": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.5.tgz", + "integrity": "sha512-Gs0qos5wqxnQrvpYv+pf3XfcRXW6jiAn9zE/K+DlmYf6FcpxeNYN0AIETaPR7rHO4K2UY+D0CIbDP9Ut0U4m1g==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@typescript-eslint/typescript-estree": "6.7.5", + "@typescript-eslint/utils": "6.7.5", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "node_modules/@typescript-eslint/types": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.5.tgz", + "integrity": "sha512-WboQBlOXtdj1tDFPyIthpKrUb+kZf2VroLZhxKa/VlwLlLyqv/PwUNgL30BlTVZV1Wu4Asu2mMYPqarSO4L5ZQ==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.3" + "engines": { + "node": "^16.0.0 || >=18.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz", - "integrity": "sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.5.tgz", + "integrity": "sha512-NhJiJ4KdtwBIxrKl0BqG1Ur+uw7FiOnOThcYx9DpOGJ/Abc9z2xNzLeirCG02Ig3vkvrc2qFLmYSSsaITbKjlg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": ">=6.9.0" + "node": "^16.0.0 || >=18.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "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==", + "node_modules/@typescript-eslint/utils": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.5.tgz", + "integrity": "sha512-pfRRrH20thJbzPPlPc4j0UNGvH1PjPlhlCMq4Yx7EGjV7lvEeGX0U6MJYe8+SyFutWgSHsdbJ3BXzZccYggezA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.7.5", + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/typescript-estree": "6.7.5", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "eslint": "^7.0.0 || ^8.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==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.5.tgz", + "integrity": "sha512-3MaWdDZtLlsexZzDSdQWsFQ9l9nL8B80Z4fImSpyllFC/KLqWQRdEcB+gGGO+N3Q2uL40EsG66wZLsohPxNXvg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@typescript-eslint/types": "6.7.5", + "eslint-visitor-keys": "^3.4.1" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", - "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "node_modules/@vitejs/plugin-vue": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.4.0.tgz", + "integrity": "sha512-xdguqb+VUwiRpSg+nsc2HtbAUSGak25DXYvpQQi4RVU1Xq1uworyoH/md9Rfd8zMmPR/pSghr309QNcftUVseg==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, "engines": { - "node": ">=6.9.0" + "node": "^14.18.0 || >=16.0.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "vite": "^4.0.0", + "vue": "^3.2.25" } }, - "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==", + "node_modules/@vitest/expect": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.6.tgz", + "integrity": "sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@vitest/spy": "0.34.6", + "@vitest/utils": "0.34.6", + "chai": "^4.3.10" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "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==", + "node_modules/@vitest/runner": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.6.tgz", + "integrity": "sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@vitest/utils": "0.34.6", + "p-limit": "^4.0.0", + "pathe": "^1.1.1" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "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==", + "node_modules/@vitest/runner/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "yocto-queue": "^1.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/@vitest/runner/node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "engines": { + "node": ">=12.20" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/@vitest/snapshot": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.6.tgz", + "integrity": "sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "magic-string": "^0.30.1", + "pathe": "^1.1.1", + "pretty-format": "^29.5.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "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==", + "node_modules/@vitest/spy": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.6.tgz", + "integrity": "sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "tinyspy": "^2.1.1" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "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==", + "node_modules/@vitest/utils": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.6.tgz", + "integrity": "sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" + "diff-sequences": "^29.4.3", + "loupe": "^2.3.6", + "pretty-format": "^29.5.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "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==", + "node_modules/@volar/language-core": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-1.10.1.tgz", + "integrity": "sha512-JnsM1mIPdfGPxmoOcK1c7HYAsL6YOv0TCJ4aW3AXPZN/Jb4R77epDyMZIVudSGjWMbvv/JfUa+rQ+dGKTmgwBA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@volar/source-map": "1.10.1" } }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz", - "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==", + "node_modules/@volar/source-map": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-1.10.1.tgz", + "integrity": "sha512-3/S6KQbqa7pGC8CxPrg69qHLpOvkiPHGJtWPkI/1AXCsktkJ6gIk/5z4hyuMp8Anvs6eS/Kvp/GZa3ut3votKA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "muggle-string": "^0.3.1" } }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz", - "integrity": "sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==", + "node_modules/@volar/typescript": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-1.10.1.tgz", + "integrity": "sha512-+iiO9yUSRHIYjlteT+QcdRq8b44qH19/eiUZtjNtuh6D9ailYM7DVR0zO2sEgJlvCaunw/CF9Ov2KooQBpR4VQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@volar/language-core": "1.10.1" } }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz", - "integrity": "sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==", - "dev": true, + "node_modules/@vue/compiler-core": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.4.tgz", + "integrity": "sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==", "dependencies": { - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-remap-async-to-generator": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/parser": "^7.21.3", + "@vue/shared": "3.3.4", + "estree-walker": "^2.0.2", + "source-map-js": "^1.0.2" } }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", - "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", - "dev": true, + "node_modules/@vue/compiler-dom": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.4.tgz", + "integrity": "sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@vue/compiler-core": "3.3.4", + "@vue/shared": "3.3.4" } }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.6.tgz", - "integrity": "sha512-pRqwb91C42vs1ahSAWJkxOxU1RHWDn16XAa6ggQ72wjLlWyYeAcLvTtE0aM8ph3KNydy9CQF2nLYcjq1WysgxQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node_modules/@vue/compiler-sfc": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.4.tgz", + "integrity": "sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==", + "dependencies": { + "@babel/parser": "^7.20.15", + "@vue/compiler-core": "3.3.4", + "@vue/compiler-dom": "3.3.4", + "@vue/compiler-ssr": "3.3.4", + "@vue/reactivity-transform": "3.3.4", + "@vue/shared": "3.3.4", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.0", + "postcss": "^8.1.10", + "source-map-js": "^1.0.2" } }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.8.tgz", - "integrity": "sha512-RySDoXdF6hgHSHuAW4aLGyVQdmvEX/iJtjVre52k0pxRq4hzqze+rAVP++NmNv596brBpYmaiKgTZby7ziBnVg==", - "dev": true, + "node_modules/@vue/compiler-ssr": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.4.tgz", + "integrity": "sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.6", - "@babel/helper-function-name": "^7.18.6", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@vue/compiler-dom": "3.3.4", + "@vue/shared": "3.3.4" } }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.6.tgz", - "integrity": "sha512-9repI4BhNrR0KenoR9vm3/cIc1tSBIo+u1WVjKCAynahj25O8zfbiE6JtAtHPGQSs4yZ+bA8mRasRP+qc+2R5A==", + "node_modules/@vue/devtools-api": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.5.0.tgz", + "integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==" + }, + "node_modules/@vue/eslint-config-prettier": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-8.0.0.tgz", + "integrity": "sha512-55dPqtC4PM/yBjhAr+yEw6+7KzzdkBuLmnhBrDfp4I48+wy+Giqqj9yUr5T2uD/BkBROjjmqnLZmXRdOx/VtQg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-prettier": "^5.0.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "eslint": ">= 8.0.0", + "prettier": ">= 3.0.0" } }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.6.tgz", - "integrity": "sha512-tgy3u6lRp17ilY8r1kP4i2+HDUwxlVqq3RTc943eAWSzGgpU1qhiKpqZ5CMyHReIYPHdo3Kg8v8edKtDqSVEyQ==", + "node_modules/@vue/eslint-config-typescript": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-12.0.0.tgz", + "integrity": "sha512-StxLFet2Qe97T8+7L8pGlhYBBr8Eg05LPuTDVopQV6il+SK6qqom59BA/rcFipUef2jD8P2X44Vd8tMFytfvlg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@typescript-eslint/eslint-plugin": "^6.7.0", + "@typescript-eslint/parser": "^6.7.0", + "vue-eslint-parser": "^9.3.1" }, "engines": { - "node": ">=6.9.0" + "node": "^14.17.0 || >=16.0.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0", + "eslint-plugin-vue": "^9.0.0", + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", - "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", + "node_modules/@vue/language-core": { + "version": "1.8.15", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.15.tgz", + "integrity": "sha512-zche5Aw8kkvp3YaghuLiOZyVIpoWHjSQ0EfjxGSsqHOPMamdCoa9x3HtbenpR38UMUoKJ88wiWuiOrV3B/Yq+A==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" + "@volar/language-core": "~1.10.0", + "@volar/source-map": "~1.10.0", + "@vue/compiler-dom": "^3.3.0", + "@vue/reactivity": "^3.3.0", + "@vue/shared": "^3.3.0", + "minimatch": "^9.0.0", + "muggle-string": "^0.3.1", + "vue-template-compiler": "^2.7.14" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.6.tgz", - "integrity": "sha512-NJU26U/208+sxYszf82nmGYqVF9QN8py2HFTblPT9hbawi8+1C5a9JubODLTGFuT0qlkqVinmkwOD13s0sZktg==", + "node_modules/@vue/language-core/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "balanced-match": "^1.0.0" } }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", - "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", + "node_modules/@vue/language-core/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=6.9.0" + "node": ">=16 || 14 >=14.17" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz", - "integrity": "sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==", - "dev": true, + "node_modules/@vue/reactivity": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.4.tgz", + "integrity": "sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@vue/shared": "3.3.4" } }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.6.tgz", - "integrity": "sha512-kJha/Gbs5RjzIu0CxZwf5e3aTTSlhZnHMT8zPWnJMjNpLOUgqevg+PN5oMH68nMCXnfiMo4Bhgxqj59KHTlAnA==", - "dev": true, + "node_modules/@vue/reactivity-transform": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.3.4.tgz", + "integrity": "sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==", "dependencies": { - "@babel/helper-compilation-targets": "^7.18.6", - "@babel/helper-function-name": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/parser": "^7.20.15", + "@vue/compiler-core": "3.3.4", + "@vue/shared": "3.3.4", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.0" } }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.6.tgz", - "integrity": "sha512-x3HEw0cJZVDoENXOp20HlypIHfl0zMIhMVZEBVTfmqbObIpsMxMbmU5nOEO8R7LYT+z5RORKPlTI5Hj4OsO9/Q==", - "dev": true, + "node_modules/@vue/runtime-core": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.3.4.tgz", + "integrity": "sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@vue/reactivity": "3.3.4", + "@vue/shared": "3.3.4" } }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", - "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", - "dev": true, + "node_modules/@vue/runtime-dom": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.3.4.tgz", + "integrity": "sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@vue/runtime-core": "3.3.4", + "@vue/shared": "3.3.4", + "csstype": "^3.1.1" } }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz", - "integrity": "sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg==", - "dev": true, + "node_modules/@vue/server-renderer": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.3.4.tgz", + "integrity": "sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==", "dependencies": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "babel-plugin-dynamic-import-node": "^2.3.3" - }, - "engines": { - "node": ">=6.9.0" + "@vue/compiler-ssr": "3.3.4", + "@vue/shared": "3.3.4" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "vue": "3.3.4" } }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz", - "integrity": "sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q==", + "node_modules/@vue/shared": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz", + "integrity": "sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==" + }, + "node_modules/@vue/test-utils": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.4.1.tgz", + "integrity": "sha512-VO8nragneNzUZUah6kOjiFmD/gwRjUauG9DROh6oaOeFwX1cZRUNHhdeogE8635cISigXFTtGLUQWx5KCb0xeg==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-simple-access": "^7.18.6", - "babel-plugin-dynamic-import-node": "^2.3.3" - }, - "engines": { - "node": ">=6.9.0" + "js-beautify": "1.14.9", + "vue-component-type-helpers": "1.8.4" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@vue/server-renderer": "^3.0.1", + "vue": "^3.0.1" + }, + "peerDependenciesMeta": { + "@vue/server-renderer": { + "optional": true + } } }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.6.tgz", - "integrity": "sha512-UbPYpXxLjTw6w6yXX2BYNxF3p6QY225wcTkfQCy3OMnSlS/C3xGtwUjEzGkldb/sy6PWLiCQ3NbYfjWUTI3t4g==", + "node_modules/@vue/tsconfig": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@vue/tsconfig/-/tsconfig-0.4.0.tgz", + "integrity": "sha512-CPuIReonid9+zOG/CGTT05FXrPYATEqoDGNrEaqS4hwcw5BUNM2FguC0mOwJD4Jr16UpRVl9N0pY3P+srIbqmg==", + "dev": true + }, + "node_modules/@vue/typescript": { + "version": "1.8.15", + "resolved": "https://registry.npmjs.org/@vue/typescript/-/typescript-1.8.15.tgz", + "integrity": "sha512-qWyanQKXOsK84S8rP7QBrqsvUdQ0nZABZmTjXMpb3ox4Bp5IbkscREA3OPUrkgl64mAxwwCzIWcOc3BPTCPjQw==", "dev": true, "dependencies": { - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-validator-identifier": "^7.18.6", - "babel-plugin-dynamic-import-node": "^2.3.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@volar/typescript": "~1.10.0", + "@vue/language-core": "1.8.15" } }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", - "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "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/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=0.4.0" } }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.18.6.tgz", - "integrity": "sha512-UmEOGF8XgaIqD74bC8g7iV3RYj8lMf0Bw7NJzvnS9qQhM4mg+1WHKotUIdjxgD2RGrgFLZZPCFPFj3P/kVDYhg==", + "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, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, "peerDependencies": { - "@babel/core": "^7.0.0" + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", - "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=0.4.0" } }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", - "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", + "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": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.6" + "debug": "4" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 6.0.0" } }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz", - "integrity": "sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg==", + "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": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", - "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", + "node_modules/ansi-escapes": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz", + "integrity": "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "type-fest": "^1.0.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=12" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz", - "integrity": "sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==", + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "regenerator-transform": "^0.15.0" - }, "engines": { - "node": ">=6.9.0" + "node": ">=10" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", - "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", + "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, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=8" } }, - "node_modules/@babel/plugin-transform-runtime": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.18.6.tgz", - "integrity": "sha512-8uRHk9ZmRSnWqUgyae249EJZ94b0yAGLBIqzZzl+0iEdbno55Pmlt/32JZsHwXD9k/uZj18Aqqk35wBX4CBTXA==", + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "babel-plugin-polyfill-corejs2": "^0.3.1", - "babel-plugin-polyfill-corejs3": "^0.5.2", - "babel-plugin-polyfill-regenerator": "^0.3.1", - "semver": "^6.3.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=6.9.0" + "node": ">=8" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", - "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, + "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, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 8" } }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.18.6.tgz", - "integrity": "sha512-ayT53rT/ENF8WWexIRg9AiV9h0aIteyWn5ptfZTZQrjk/+f3WdrJGCY4c9wcgl2+MKkKPhzbYp97FTsquZpDCw==", + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", - "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=8" } }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.6.tgz", - "integrity": "sha512-UuqlRrQmT2SWRvahW46cGSany0uTlcj8NYOS5sRGYi8FxPYPoLd5DDmMd32ZXEj2Jq+06uGVQKHxa/hJx2EzKw==", + "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==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "*" } }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.6.tgz", - "integrity": "sha512-7m71iS/QhsPk85xSjFPovHPcH3H9qeyzsujhTc+vcdnsXavoWYJ74zx0lP5RhpC5+iDnVLO+PPMHzC11qels1g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "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 }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.6.tgz", - "integrity": "sha512-XNRwQUXYMP7VLuy54cr/KS/WeL3AZeORhrmeZ7iewgu+X2eBqmpaLI/hzqr9ZxCeUoq0ASK4GUzSM0BDhZkLFw==", + "node_modules/autoprefixer": { + "version": "10.4.15", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.15.tgz", + "integrity": "sha512-KCuPB8ZCIqFdA4HwKXsvz7j6gvSDNhDP7WnUjBleRkKjPdvCmHFuQ77ocavI8FT6NdvlBnE2UFr2H4Mycn8Vew==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "browserslist": "^4.21.10", + "caniuse-lite": "^1.0.30001520", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" }, "engines": { - "node": ">=6.9.0" + "node": "^10 || ^12 || >=14" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.1.0" } }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", - "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-env": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.6.tgz", - "integrity": "sha512-WrthhuIIYKrEFAwttYzgRNQ5hULGmwTj+D6l7Zdfsv5M7IWV/OZbUfbeL++Qrzx1nVJwWROIFhCHRYQV4xbPNw==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.18.6", - "@babel/helper-compilation-targets": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-validator-option": "^7.18.6", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.6", - "@babel/plugin-proposal-async-generator-functions": "^7.18.6", - "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-proposal-class-static-block": "^7.18.6", - "@babel/plugin-proposal-dynamic-import": "^7.18.6", - "@babel/plugin-proposal-export-namespace-from": "^7.18.6", - "@babel/plugin-proposal-json-strings": "^7.18.6", - "@babel/plugin-proposal-logical-assignment-operators": "^7.18.6", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", - "@babel/plugin-proposal-numeric-separator": "^7.18.6", - "@babel/plugin-proposal-object-rest-spread": "^7.18.6", - "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", - "@babel/plugin-proposal-optional-chaining": "^7.18.6", - "@babel/plugin-proposal-private-methods": "^7.18.6", - "@babel/plugin-proposal-private-property-in-object": "^7.18.6", - "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.18.6", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.18.6", - "@babel/plugin-transform-async-to-generator": "^7.18.6", - "@babel/plugin-transform-block-scoped-functions": "^7.18.6", - "@babel/plugin-transform-block-scoping": "^7.18.6", - "@babel/plugin-transform-classes": "^7.18.6", - "@babel/plugin-transform-computed-properties": "^7.18.6", - "@babel/plugin-transform-destructuring": "^7.18.6", - "@babel/plugin-transform-dotall-regex": "^7.18.6", - "@babel/plugin-transform-duplicate-keys": "^7.18.6", - "@babel/plugin-transform-exponentiation-operator": "^7.18.6", - "@babel/plugin-transform-for-of": "^7.18.6", - "@babel/plugin-transform-function-name": "^7.18.6", - "@babel/plugin-transform-literals": "^7.18.6", - "@babel/plugin-transform-member-expression-literals": "^7.18.6", - "@babel/plugin-transform-modules-amd": "^7.18.6", - "@babel/plugin-transform-modules-commonjs": "^7.18.6", - "@babel/plugin-transform-modules-systemjs": "^7.18.6", - "@babel/plugin-transform-modules-umd": "^7.18.6", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.18.6", - "@babel/plugin-transform-new-target": "^7.18.6", - "@babel/plugin-transform-object-super": "^7.18.6", - "@babel/plugin-transform-parameters": "^7.18.6", - "@babel/plugin-transform-property-literals": "^7.18.6", - "@babel/plugin-transform-regenerator": "^7.18.6", - "@babel/plugin-transform-reserved-words": "^7.18.6", - "@babel/plugin-transform-shorthand-properties": "^7.18.6", - "@babel/plugin-transform-spread": "^7.18.6", - "@babel/plugin-transform-sticky-regex": "^7.18.6", - "@babel/plugin-transform-template-literals": "^7.18.6", - "@babel/plugin-transform-typeof-symbol": "^7.18.6", - "@babel/plugin-transform-unicode-escapes": "^7.18.6", - "@babel/plugin-transform-unicode-regex": "^7.18.6", - "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.18.6", - "babel-plugin-polyfill-corejs2": "^0.3.1", - "babel-plugin-polyfill-corejs3": "^0.5.2", - "babel-plugin-polyfill-regenerator": "^0.3.1", - "core-js-compat": "^3.22.1", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/preset-modules": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", - "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=0.6" } }, - "node_modules/@babel/runtime": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.6.tgz", - "integrity": "sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ==", + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true, - "dependencies": { - "regenerator-runtime": "^0.13.4" - }, "engines": { - "node": ">=6.9.0" + "node": ">=8" } }, - "node_modules/@babel/template": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz", - "integrity": "sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw==", + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/bplist-parser": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", + "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.6", - "@babel/types": "^7.18.6" + "big-integer": "^1.6.44" }, "engines": { - "node": ">=6.9.0" + "node": ">= 5.10.0" } }, - "node_modules/@babel/traverse": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.6.tgz", - "integrity": "sha512-zS/OKyqmD7lslOtFqbscH6gMLFYOfG1YPqCKfAW5KrTeolKqvB8UelR49Fpr6y93kYkW2Ik00mT1LOGiAGvizw==", + "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": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.6", - "@babel/helper-function-name": "^7.18.6", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.18.6", - "@babel/types": "^7.18.6", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@babel/types": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz", - "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==", + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", - "to-fast-properties": "^2.0.0" + "fill-range": "^7.0.1" }, "engines": { - "node": ">=6.9.0" + "node": ">=8" } }, - "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/@eslint-community/eslint-utils": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.3.0.tgz", - "integrity": "sha512-v3oplH6FYCULtFuCeqyuTd9D2WKO937Dxdq+GmHOLL72TTRriLxz2VLlNfkZRsvj6PKnOPAtuT6dwrs/pA5DvA==", + "node_modules/browserslist": { + "version": "4.21.10", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", + "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", "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": { - "eslint-visitor-keys": "^3.3.0" + "caniuse-lite": "^1.0.30001517", + "electron-to-chromium": "^1.4.477", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.11" }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "bin": { + "browserslist": "cli.js" }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz", - "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==", - "dev": true, "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz", - "integrity": "sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==", + "node_modules/bundle-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", + "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", "dev": true, "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "run-applescript": "^5.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=12" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "dev": true, - "engines": { - "node": ">=10" + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@eslint/js": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz", - "integrity": "sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==", + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=6" } }, - "node_modules/@hapi/hoek": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz", - "integrity": "sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw==", - "dev": true - }, - "node_modules/@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", "dev": true, - "dependencies": { - "@hapi/hoek": "^9.0.0" + "engines": { + "node": ">= 6" } }, - "node_modules/@highlightjs/vue-plugin": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@highlightjs/vue-plugin/-/vue-plugin-2.1.0.tgz", - "integrity": "sha512-E+bmk4ncca+hBEYRV2a+1aIzIV0VSY/e5ArjpuSN9IO7wBJrzUE2u4ESCwrbQD7sAy+jWQjkV5qCCWgc+pu7CQ==", - "peerDependencies": { - "highlight.js": "^11.0.1", - "vue": "^3" - } + "node_modules/caniuse-lite": { + "version": "1.0.30001522", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001522.tgz", + "integrity": "sha512-TKiyTVZxJGhsTszLuzb+6vUZSjVOAhClszBr2Ta2k9IwtNBT/4dzmL6aywt0HCgEZlmwJzXJd8yNiob6HgwTRg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "node_modules/chai": { + "version": "4.3.10", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", + "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" + "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": ">=10.10.0" + "node": ">=4" } }, - "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==", + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=12.22" + "node": ">=10" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, + "node_modules/chart.js": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.0.tgz", + "integrity": "sha512-vQEj6d+z0dcsKLlQvbKIMYFHd3t8W/7L2vfJIbYcfyPcRx92CsHqECpueN8qVGNlKyDcr5wBrYAYKnfu/9Q1hQ==", "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" + "@kurkle/color": "^0.3.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" + "pnpm": ">=7" } }, - "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, - "engines": { - "node": ">=6" + "node_modules/chartjs-plugin-datalabels": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/chartjs-plugin-datalabels/-/chartjs-plugin-datalabels-2.2.0.tgz", + "integrity": "sha512-14ZU30lH7n89oq+A4bWaJPnAG8a7ZTk7dKf48YAzMvJjQtjrgg5Dpk9f+LbjCF6bpx3RAGTeL13IXpKQYyRvlw==", + "peerDependencies": { + "chart.js": ">=3.0.0" } }, - "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==", + "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, "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "get-func-name": "^2.0.2" }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "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": "*" } }, - "node_modules/@jest/console": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.5.0.tgz", - "integrity": "sha512-NEpkObxPwyw/XxZVLPmAGKE89IQRp4puc6IQRPru6JKd1M3fW9v1xM1AnzIJE65hbCkzQAdnL8P47e9hzhiYLQ==", + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, - "dependencies": { - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", - "slash": "^3.0.0" + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "node_modules/@jest/console/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "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, "dependencies": { - "color-convert": "^2.0.1" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=8" + "node": ">= 6" + } + }, + "node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dev": true, + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jest/console/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/cli-truncate": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", + "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "slice-ansi": "^5.0.0", + "string-width": "^5.0.0" }, "engines": { - "node": ">=10" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jest/console/node_modules/color-convert": { + "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==", @@ -2028,4105 +1909,3535 @@ "node": ">=7.0.0" } }, - "node_modules/@jest/console/node_modules/color-name": { + "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/@jest/console/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "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, + "dependencies": { + "delayed-stream": "~1.0.0" + }, "engines": { - "node": ">=8" + "node": ">= 0.8" } }, - "node_modules/@jest/console/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "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": ">=8" + "node": ">=14" } }, - "node_modules/@jest/console/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "ini": "^1.3.4", + "proto-list": "~1.2.1" } }, - "node_modules/@jest/core": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.5.0.tgz", - "integrity": "sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ==", + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "dependencies": { - "@jest/console": "^29.5.0", - "@jest/reporters": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.5.0", - "jest-config": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-resolve-dependencies": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "jest-watcher": "^29.5.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": ">= 8" } }, - "node_modules/@jest/core/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, - "dependencies": { - "color-convert": "^2.0.1" + "bin": { + "cssesc": "bin/cssesc" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=4" } }, - "node_modules/@jest/core/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/cssstyle": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-3.0.0.tgz", + "integrity": "sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "rrweb-cssom": "^0.6.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=14" } }, - "node_modules/@jest/core/node_modules/ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } + "node_modules/csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" }, - "node_modules/@jest/core/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/data-urls": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-4.0.0.tgz", + "integrity": "sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "abab": "^2.0.6", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^12.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=14" } }, - "node_modules/@jest/core/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", "dev": true }, - "node_modules/@jest/core/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "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, + "dependencies": { + "ms": "2.1.2" + }, "engines": { - "node": ">=8" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@jest/core/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } + "node_modules/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/@jest/core/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "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, "dependencies": { - "has-flag": "^4.0.0" + "type-detect": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/@jest/environment": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.5.0.tgz", - "integrity": "sha512-5FXw2+wD29YU1d4I2htpRX7jYnAyTRjP2CsXQdo9SAM8g3ifxWPSV0HnClSn71xwctr0U3oZIIH+dtbfmnbXVQ==", + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/default-browser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", + "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", "dev": true, "dependencies": { - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "jest-mock": "^29.5.0" + "bundle-name": "^3.0.0", + "default-browser-id": "^3.0.0", + "execa": "^7.1.1", + "titleize": "^3.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jest/expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-PueDR2HGihN3ciUNGr4uelropW7rqUfTiOn+8u0leg/42UhblPxHkfoh0Ruu3I9Y1962P3u2DY4+h7GVTSVU6g==", + "node_modules/default-browser-id": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", + "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", "dev": true, "dependencies": { - "expect": "^29.5.0", - "jest-snapshot": "^29.5.0" + "bplist-parser": "^0.2.0", + "untildify": "^4.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jest/expect-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", - "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", "dev": true, - "dependencies": { - "jest-get-type": "^29.4.3" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jest/fake-timers": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.5.0.tgz", - "integrity": "sha512-9ARvuAAQcBwDAqOnglWq2zwNIRUDtk/SCkp/ToGEhFv5r86K21l+VEs0qNTaXtyiY0lEePl3kylijSYJQqdbDg==", + "node_modules/define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0" + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@jest/globals": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.5.0.tgz", - "integrity": "sha512-S02y0qMWGihdzNbUiqSAiKSpSozSuHX5UYc7QbnHP+D9Lyw8DgGGCinrN9uSuHPeKgSSzvPom2q1nAtBvUsvPQ==", + "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, - "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/types": "^29.5.0", - "jest-mock": "^29.5.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.4.0" } }, - "node_modules/@jest/reporters": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.5.0.tgz", - "integrity": "sha512-D05STXqj/M8bP9hQNSICtPqz97u7ffGzZu+9XLucXhkOFBqKcXe04JLZOgIekOxdb73MAoBUFnqvf7MCpKk5OA==", - "dev": true, - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } } }, - "node_modules/@jest/reporters/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "path-type": "^4.0.0" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@jest/reporters/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "esutils": "^2.0.2" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=6.0.0" } }, - "node_modules/@jest/reporters/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/domexception": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", + "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "webidl-conversions": "^7.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=12" } }, - "node_modules/@jest/reporters/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, - "node_modules/@jest/reporters/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/editorconfig": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", + "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==", "dev": true, + "dependencies": { + "@one-ini/wasm": "0.1.1", + "commander": "^10.0.0", + "minimatch": "9.0.1", + "semver": "^7.5.3" + }, + "bin": { + "editorconfig": "bin/editorconfig" + }, "engines": { - "node": ">=8" + "node": ">=14" } }, - "node_modules/@jest/reporters/node_modules/jest-worker": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", - "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", + "node_modules/editorconfig/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "@types/node": "*", - "jest-util": "^29.5.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "balanced-match": "^1.0.0" } }, - "node_modules/@jest/reporters/node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/editorconfig/node_modules/minimatch": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", + "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@jest/reporters/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "node_modules/electron-to-chromium": { + "version": "1.4.499", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.499.tgz", + "integrity": "sha512-0NmjlYBLKVHva4GABWAaHuPJolnDuL0AhV3h1hES6rcLCWEIbRL6/8TghfsVwkx6TEroQVdliX7+aLysUpKvjw==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/entities": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", + "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", "dev": true, "engines": { - "node": ">=8" + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/@jest/reporters/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "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": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "is-arrayish": "^0.2.1" } }, - "node_modules/@jest/schemas": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "node_modules/es-abstract": { + "version": "1.21.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", + "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.25.16" + "array-buffer-byte-length": "^1.0.0", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.2.0", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.9" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@jest/source-map": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.4.3.tgz", - "integrity": "sha512-qyt/mb6rLyd9j1jUts4EQncvS6Yy3PM9HghnNv86QBlV+zdL2inCdK1tuVlL+J+lpiw2BI67qXOrX3UurBqQ1w==", + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.15", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" } }, - "node_modules/@jest/test-result": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.5.0.tgz", - "integrity": "sha512-fGl4rfitnbfLsrfx1uUpDEESS7zM8JdgZgOCQuxQvL1Sn/I6ijeAVQWGfXI9zb1i9Mzo495cIpVZhA0yr60PkQ==", + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, "dependencies": { - "@jest/console": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@jest/test-sequencer": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.5.0.tgz", - "integrity": "sha512-yPafQEcKjkSfDXyvtgiV4pevSeyuA6MQr6ZIdVkWJly9vkqjnFfcfhRQqpD5whjoU8EORki752xQmjaqoFjzMQ==", + "node_modules/esbuild": { + "version": "0.18.14", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.14.tgz", + "integrity": "sha512-uNPj5oHPYmj+ZhSQeYQVFZ+hAlJZbAGOmmILWIqrGvPVlNLbyOvU5Bu6Woi8G8nskcx0vwY0iFoMPrzT86Ko+w==", "dev": true, - "dependencies": { - "@jest/test-result": "^29.5.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "slash": "^3.0.0" + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.18.14", + "@esbuild/android-arm64": "0.18.14", + "@esbuild/android-x64": "0.18.14", + "@esbuild/darwin-arm64": "0.18.14", + "@esbuild/darwin-x64": "0.18.14", + "@esbuild/freebsd-arm64": "0.18.14", + "@esbuild/freebsd-x64": "0.18.14", + "@esbuild/linux-arm": "0.18.14", + "@esbuild/linux-arm64": "0.18.14", + "@esbuild/linux-ia32": "0.18.14", + "@esbuild/linux-loong64": "0.18.14", + "@esbuild/linux-mips64el": "0.18.14", + "@esbuild/linux-ppc64": "0.18.14", + "@esbuild/linux-riscv64": "0.18.14", + "@esbuild/linux-s390x": "0.18.14", + "@esbuild/linux-x64": "0.18.14", + "@esbuild/netbsd-x64": "0.18.14", + "@esbuild/openbsd-x64": "0.18.14", + "@esbuild/sunos-x64": "0.18.14", + "@esbuild/win32-arm64": "0.18.14", + "@esbuild/win32-ia32": "0.18.14", + "@esbuild/win32-x64": "0.18.14" } }, - "node_modules/@jest/test-sequencer/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/@jest/transform": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.5.0.tgz", - "integrity": "sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw==", + "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, - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jest/transform/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/eslint": { + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz", + "integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "8.51.0", + "@humanwhocodes/config-array": "^0.11.11", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" }, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://opencollective.com/eslint" } }, - "node_modules/@jest/transform/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/eslint-config-prettier": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", + "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" + "bin": { + "eslint-config-prettier": "bin/cli.js" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "peerDependencies": { + "eslint": ">=7.0.0" } }, - "node_modules/@jest/transform/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/eslint-plugin-prettier": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.0.tgz", + "integrity": "sha512-AgaZCVuYDXHUGxj/ZGu1u8H8CYgDY3iG6w5kUFw4AzMVXzB7VvbKgYR4nATIN+OvUrghMbiDLeimVjVY5ilq3w==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.5" }, "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@jest/transform/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@jest/transform/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/@jest/transform/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/transform/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } } }, - "node_modules/@jest/transform/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/eslint-plugin-vue": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.17.0.tgz", + "integrity": "sha512-r7Bp79pxQk9I5XDP0k2dpUC7Ots3OSWgvGZNu3BxmKK6Zg7NgVtcOB6OCna5Kb9oQwJPl5hq183WD0SY5tZtIQ==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "@eslint-community/eslint-utils": "^4.4.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.1.1", + "postcss-selector-parser": "^6.0.13", + "semver": "^7.5.4", + "vue-eslint-parser": "^9.3.1", + "xml-name-validator": "^4.0.0" }, "engines": { - "node": ">=8" + "node": "^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@jest/types": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", - "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", + "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, - "dependencies": { - "@jest/schemas": "^29.4.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@jest/types/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://opencollective.com/eslint" } }, - "node_modules/@jest/types/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://opencollective.com/eslint" } }, - "node_modules/@jest/types/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "estraverse": "^5.1.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=0.10" } }, - "node_modules/@jest/types/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@jest/types/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, "engines": { - "node": ">=8" + "node": ">=4.0" } }, - "node_modules/@jest/types/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=8" + "node": ">=4.0" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, "engines": { - "node": ">=6.0.0" + "node": ">=4.0" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "engines": { - "node": ">=6.0.0" - } + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, "engines": { - "node": ">=6.0.0" + "node": ">=0.10.0" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true + }, + "node_modules/execa": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", + "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true }, - "node_modules/@node-ipc/js-queue": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@node-ipc/js-queue/-/js-queue-2.0.3.tgz", - "integrity": "sha512-fL1wpr8hhD5gT2dA1qifeVaoDFlQR5es8tFuKqjHX+kdOtdNHnxkVZbtIrR2rxnMFvehkjaZRNV2H/gPXlb0hw==", + "node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", "dev": true, "dependencies": { - "easy-stack": "1.0.1" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" }, "engines": { - "node": ">=1.0.0" + "node": ">=8.6.0" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "is-glob": "^4.0.1" }, "engines": { - "node": ">= 8" + "node": ">= 6" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, - "engines": { - "node": ">= 8" + "dependencies": { + "reusify": "^1.0.4" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "flat-cache": "^3.0.4" }, "engines": { - "node": ">= 8" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/@polka/url": { - "version": "1.0.0-next.21", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", - "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==", - "dev": true - }, - "node_modules/@sideway/address": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.3.tgz", - "integrity": "sha512-8ncEUtmnTsMmL7z1YPB47kPUq7LpKWJNFPsRzHiIajGC5uXlWGn+AmkYPcHNl8S4tcEGx+cnORnNYaw2wvL+LQ==", + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@sideway/formula": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", - "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", - "dev": true - }, - "node_modules/@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", - "dev": true - }, - "node_modules/@sinclair/typebox": { - "version": "0.25.24", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", - "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", - "dev": true - }, - "node_modules/@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz", - "integrity": "sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==", + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "dependencies": { - "@sinonjs/commons": "^2.0.0" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@soda/friendly-errors-webpack-plugin": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.8.1.tgz", - "integrity": "sha512-h2ooWqP8XuFqTXT+NyAFbrArzfQA7R6HTezADrvD9Re8fxMLTPPniLdqVTdDaO0eIoLaAwKT+d6w+5GeTk7Vbg==", + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dev": true, "dependencies": { - "chalk": "^3.0.0", - "error-stack-parser": "^2.0.6", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" + "flatted": "^3.1.0", + "rimraf": "^3.0.2" }, "engines": { - "node": ">=8.0.0" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "is-callable": "^1.1.3" } }, - "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" }, "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, "engines": { - "node": ">=7.0.0" + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/infusion" } }, - "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, - "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "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" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@soda/get-current-script": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@soda/get-current-script/-/get-current-script-1.0.2.tgz", - "integrity": "sha512-T7VNNlYVM1SgQ+VsMYhnDkcGmWhQdL0bDyGm5TlQ3GBXnJscEClUUOKduWTmm2zCnvNLC1hc3JpuXjs/nFOc5w==", - "dev": true - }, - "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/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, - "engines": { - "node": ">= 10" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "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, "engines": { - "node": ">=10.13.0" + "node": "*" } }, - "node_modules/@types/babel__core": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz", - "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==", + "node_modules/get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", "dev": true, "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, - "dependencies": { - "@babel/types": "^7.0.0" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", "dev": true, "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@types/babel__traverse": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", - "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", + "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, "dependencies": { - "@babel/types": "^7.3.0" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "dependencies": { - "@types/connect": "*", - "@types/node": "*" + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" } }, - "node_modules/@types/bonjour": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", - "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "@types/node": "*" + "balanced-match": "^1.0.0" } }, - "node_modules/@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "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, "dependencies": { - "@types/node": "*" + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@types/connect-history-api-fallback": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz", - "integrity": "sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==", + "node_modules/globals": { + "version": "13.21.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", + "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", "dev": true, "dependencies": { - "@types/express-serve-static-core": "*", - "@types/node": "*" + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@types/eslint": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.29.0.tgz", - "integrity": "sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng==", + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@types/eslint-scope": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", - "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@types/estree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==" - }, - "node_modules/@types/express": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", - "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "node_modules/globby/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" + "engines": { + "node": ">=8" } }, - "node_modules/@types/express-serve-static-core": { - "version": "4.17.28", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", - "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dev": true, "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@types/graceful-fs": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", - "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "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/@types/http-proxy": { - "version": "1.17.8", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz", - "integrity": "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "dependencies": { - "@types/istanbul-lib-coverage": "*" + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" } }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", "dev": true, - "dependencies": { - "@types/istanbul-lib-report": "*" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@types/jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.0.tgz", - "integrity": "sha512-3Emr5VOl/aoBwnWcH/EFQvlSAmjV+XtV9GGu5mwdYew5vhQh0IUZx/60x0TzHDu09Bi7HMx10t/namdJw5QIcg==", + "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, - "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" + "engines": { + "node": ">=8" } }, - "node_modules/@types/jsdom": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", - "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", "dev": true, "dependencies": { - "@types/node": "*", - "@types/tough-cookie": "*", - "parse5": "^7.0.0" + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@types/jsdom/node_modules/entities": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", - "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", "dev": true, "engines": { - "node": ">=0.12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@types/jsdom/node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "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, - "dependencies": { - "entities": "^4.4.0" + "engines": { + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==" - }, - "node_modules/@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", - "dev": true - }, - "node_modules/@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true - }, - "node_modules/@types/node": { - "version": "17.0.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.18.tgz", - "integrity": "sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA==" - }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true - }, - "node_modules/@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true - }, - "node_modules/@types/prettier": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", - "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", - "dev": true - }, - "node_modules/@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "dev": true - }, - "node_modules/@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "dev": true - }, - "node_modules/@types/retry": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", - "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==", - "dev": true - }, - "node_modules/@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", - "dev": true - }, - "node_modules/@types/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", "dev": true, "dependencies": { - "@types/express": "*" + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@types/serve-static": { - "version": "1.13.10", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", - "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "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, - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" + "bin": { + "he": "bin/he" } }, - "node_modules/@types/sockjs": { - "version": "0.3.33", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", - "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", - "dev": true, - "dependencies": { - "@types/node": "*" + "node_modules/highlight.js": { + "version": "11.9.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.9.0.tgz", + "integrity": "sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==", + "engines": { + "node": ">=12.0.0" } }, - "node_modules/@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "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/@types/strip-bom": { + "node_modules/html-encoding-sniffer": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==", - "dev": true - }, - "node_modules/@types/strip-json-comments": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", - "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", - "dev": true - }, - "node_modules/@types/tough-cookie": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz", - "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==", - "dev": true - }, - "node_modules/@types/webpack-env": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.16.3.tgz", - "integrity": "sha512-9gtOPPkfyNoEqCQgx4qJKkuNm/x0R2hKR7fdl7zvTJyHnIisuE/LfvXOsYWL0o3qq6uiBnKZNNNzi3l0y/X+xw==", - "dev": true - }, - "node_modules/@types/ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-ahRJZquUYCdOZf/rCsWg88S0/+cb9wazUBHv6HZEe3XdYaBe2zr/slM8J28X07Hn88Pnm4ezo7N8/ofnOgrPVQ==", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", "dev": true, "dependencies": { - "@types/node": "*" + "whatwg-encoding": "^2.0.0" + }, + "engines": { + "node": ">=12" } }, - "node_modules/@types/yargs": { - "version": "17.0.20", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.20.tgz", - "integrity": "sha512-eknWrTHofQuPk2iuqDm1waA7V6xPlbgBoaaXEgYkClhLOnB0TtbW+srJaOToAgawPxPlHQzwypFA2bhZaUGP5A==", + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", "dev": true, "dependencies": { - "@types/yargs-parser": "*" + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.56.0.tgz", - "integrity": "sha512-ZNW37Ccl3oMZkzxrYDUX4o7cnuPgU+YrcaYXzsRtLB16I1FR5SHMqga3zGsaSliZADCWo2v8qHWqAYIj8nWCCg==", + "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": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.56.0", - "@typescript-eslint/type-utils": "5.56.0", - "@typescript-eslint/utils": "5.56.0", - "debug": "^4.3.4", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "agent-base": "6", + "debug": "4" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">= 6" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.56.0.tgz", - "integrity": "sha512-jGYKyt+iBakD0SA5Ww8vFqGpoV2asSjwt60Gl6YcO8ksQ8s2HlUEyHBMSa38bdLopYqGf7EYQMUIGdT/Luw+sw==", + "node_modules/human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.56.0", - "@typescript-eslint/visitor-keys": "5.56.0" - }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=14.18.0" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.56.0.tgz", - "integrity": "sha512-JyAzbTJcIyhuUhogmiu+t79AkdnqgPUEsxMTMc/dCZczGMJQh1MK2wgrju++yMN6AWroVAy2jxyPcPr3SWCq5w==", + "node_modules/husky": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", + "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", "dev": true, + "bin": { + "husky": "lib/bin.js" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=14" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/sponsors/typicode" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.56.0.tgz", - "integrity": "sha512-1mFdED7u5bZpX6Xxf5N9U2c18sb+8EvU3tyOIj6LQZ5OOvnmj8BVeNNP603OFPm5KkS1a7IvCIcwrdHXaEMG/Q==", + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.56.0", - "eslint-visitor-keys": "^3.3.0" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=0.10.0" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, "engines": { - "node": ">=10" + "node": ">= 4" } }, - "node_modules/@typescript-eslint/parser": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.55.0.tgz", - "integrity": "sha512-ppvmeF7hvdhUUZWSd2EEWfzcFkjJzgNQzVST22nzg958CR+sphy8A6K7LXQZd6V75m1VKjp+J4g/PCEfSCmzhw==", + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.55.0", - "@typescript-eslint/types": "5.55.0", - "@typescript-eslint/typescript-estree": "5.55.0", - "debug": "^4.3.4" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=6" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.55.0.tgz", - "integrity": "sha512-OK+cIO1ZGhJYNCL//a3ROpsd83psf4dUJ4j7pdNVzd5DmIk+ffkuUIX2vcZQbEW/IR41DYsfJTB19tpCboxQuw==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.55.0", - "@typescript-eslint/visitor-keys": "5.55.0" - }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=0.8.19" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.56.0.tgz", - "integrity": "sha512-8WxgOgJjWRy6m4xg9KoSHPzBNZeQbGlQOH7l2QEhQID/+YseaFxg5J/DLwWSsi9Axj4e/cCiKx7PVzOq38tY4A==", + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.56.0", - "@typescript-eslint/utils": "5.56.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.56.0.tgz", - "integrity": "sha512-JyAzbTJcIyhuUhogmiu+t79AkdnqgPUEsxMTMc/dCZczGMJQh1MK2wgrju++yMN6AWroVAy2jxyPcPr3SWCq5w==", + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "engines": { + "node": ">= 0.4" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.56.0.tgz", - "integrity": "sha512-41CH/GncsLXOJi0jb74SnC7jVPWeVJ0pxQj8bOjH1h2O26jXN3YHKDT1ejkVz5YeTEQPeLCCRY0U2r68tfNOcg==", + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.56.0", - "@typescript-eslint/visitor-keys": "5.56.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.56.0.tgz", - "integrity": "sha512-1mFdED7u5bZpX6Xxf5N9U2c18sb+8EvU3tyOIj6LQZ5OOvnmj8BVeNNP603OFPm5KkS1a7IvCIcwrdHXaEMG/Q==", + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.56.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "has-bigints": "^1.0.1" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "binary-extensions": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/@typescript-eslint/types": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.55.0.tgz", - "integrity": "sha512-M4iRh4AG1ChrOL6Y+mETEKGeDnT7Sparn6fhZ5LtVJF1909D5O4uqK+C5NPbLmpfZ0XIIxCdwzKiijpZUOvOug==", + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.55.0.tgz", - "integrity": "sha512-I7X4A9ovA8gdpWMpr7b1BN9eEbvlEtWhQvpxp/yogt48fy9Lj3iE3ild/1H3jKBBIYj5YYJmS2+9ystVhC7eaQ==", + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.55.0", - "@typescript-eslint/visitor-keys": "5.55.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "node_modules/is-core-module": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "has": "^1.0.3" }, - "engines": { - "node": ">=10" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@typescript-eslint/utils": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.56.0.tgz", - "integrity": "sha512-XhZDVdLnUJNtbzaJeDSCIYaM+Tgr59gZGbFuELgF7m0IY03PlciidS7UQNKLE0+WpUTn1GlycEr6Ivb/afjbhA==", + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.56.0", - "@typescript-eslint/types": "5.56.0", - "@typescript-eslint/typescript-estree": "5.56.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.56.0.tgz", - "integrity": "sha512-jGYKyt+iBakD0SA5Ww8vFqGpoV2asSjwt60Gl6YcO8ksQ8s2HlUEyHBMSa38bdLopYqGf7EYQMUIGdT/Luw+sw==", + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.56.0", - "@typescript-eslint/visitor-keys": "5.56.0" + "bin": { + "is-docker": "cli.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.56.0.tgz", - "integrity": "sha512-JyAzbTJcIyhuUhogmiu+t79AkdnqgPUEsxMTMc/dCZczGMJQh1MK2wgrju++yMN6AWroVAy2jxyPcPr3SWCq5w==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=0.10.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.56.0.tgz", - "integrity": "sha512-41CH/GncsLXOJi0jb74SnC7jVPWeVJ0pxQj8bOjH1h2O26jXN3YHKDT1ejkVz5YeTEQPeLCCRY0U2r68tfNOcg==", + "node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.56.0", - "@typescript-eslint/visitor-keys": "5.56.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.56.0.tgz", - "integrity": "sha512-1mFdED7u5bZpX6Xxf5N9U2c18sb+8EvU3tyOIj6LQZ5OOvnmj8BVeNNP603OFPm5KkS1a7IvCIcwrdHXaEMG/Q==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.56.0", - "eslint-visitor-keys": "^3.3.0" + "is-extglob": "^2.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=0.10.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" + "is-docker": "^3.0.0" }, "bin": { - "semver": "bin/semver.js" + "is-inside-container": "cli.js" }, "engines": { - "node": ">=10" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.55.0.tgz", - "integrity": "sha512-q2dlHHwWgirKh1D3acnuApXG+VNXpEY5/AwRxDVuEQpxWaB0jCDe0jFMVMALJ3ebSfuOVE8/rMS+9ZOYGg1GWw==", + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.55.0", - "eslint-visitor-keys": "^3.3.0" - }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@vue/babel-helper-vue-jsx-merge-props": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.2.1.tgz", - "integrity": "sha512-QOi5OW45e2R20VygMSNhyQHvpdUwQZqGPc748JLGCYEy+yp8fNFNdbNIGAgZmi9e+2JHPd6i6idRuqivyicIkA==", - "dev": true - }, - "node_modules/@vue/babel-helper-vue-transform-on": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.0.2.tgz", - "integrity": "sha512-hz4R8tS5jMn8lDq6iD+yWL6XNB699pGIVLk7WSJnn1dbpjaazsjZQkieJoRX6gW5zpYSCFqQ7jUquPNY65tQYA==", - "dev": true - }, - "node_modules/@vue/babel-plugin-jsx": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.1.1.tgz", - "integrity": "sha512-j2uVfZjnB5+zkcbc/zsOc0fSNGCMMjaEXP52wdwdIfn0qjFfEYpYZBFKFg+HHnQeJCVrjOeO0YxgaL7DMrym9w==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/plugin-syntax-jsx": "^7.0.0", - "@babel/template": "^7.0.0", - "@babel/traverse": "^7.0.0", - "@babel/types": "^7.0.0", - "@vue/babel-helper-vue-transform-on": "^1.0.2", - "camelcase": "^6.0.0", - "html-tags": "^3.1.0", - "svg-tags": "^1.0.0" + "engines": { + "node": ">=0.12.0" } }, - "node_modules/@vue/babel-plugin-transform-vue-jsx": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@vue/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-1.2.1.tgz", - "integrity": "sha512-HJuqwACYehQwh1fNT8f4kyzqlNMpBuUK4rSiSES5D4QsYncv5fxFsLyrxFPG2ksO7t5WP+Vgix6tt6yKClwPzA==", + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dev": true, "dependencies": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/plugin-syntax-jsx": "^7.2.0", - "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1", - "html-tags": "^2.0.0", - "lodash.kebabcase": "^4.1.1", - "svg-tags": "^1.0.0" + "has-tostringtag": "^1.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@vue/babel-plugin-transform-vue-jsx/node_modules/html-tags": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", - "integrity": "sha512-+Il6N8cCo2wB/Vd3gqy/8TZhTD3QvcVeQLCnZiGkGCH3JP28IgGAY41giccp2W4R3jfyJPAP318FQTa1yU7K7g==", + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/@vue/babel-preset-app": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@vue/babel-preset-app/-/babel-preset-app-5.0.8.tgz", - "integrity": "sha512-yl+5qhpjd8e1G4cMXfORkkBlvtPCIgmRf3IYCWYDKIQ7m+PPa5iTm4feiNmCMD6yGqQWMhhK/7M3oWGL9boKwg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.16", - "@babel/helper-compilation-targets": "^7.12.16", - "@babel/helper-module-imports": "^7.12.13", - "@babel/plugin-proposal-class-properties": "^7.12.13", - "@babel/plugin-proposal-decorators": "^7.12.13", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-jsx": "^7.12.13", - "@babel/plugin-transform-runtime": "^7.12.15", - "@babel/preset-env": "^7.12.16", - "@babel/runtime": "^7.12.13", - "@vue/babel-plugin-jsx": "^1.0.3", - "@vue/babel-preset-jsx": "^1.1.2", - "babel-plugin-dynamic-import-node": "^2.3.3", - "core-js": "^3.8.3", - "core-js-compat": "^3.8.3", - "semver": "^7.3.4" - }, - "peerDependencies": { - "@babel/core": "*", - "core-js": "^3", - "vue": "^2 || ^3.2.13" - }, - "peerDependenciesMeta": { - "core-js": { - "optional": true - }, - "vue": { - "optional": true - } - } + "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/@vue/babel-preset-app/node_modules/@vue/babel-preset-jsx": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@vue/babel-preset-jsx/-/babel-preset-jsx-1.3.0.tgz", - "integrity": "sha512-WFHjZWoUV/W0VAnEM/vi3zhdKsWrYf1TVFuxrpMQXVjhU8w8cxAUzNkmUDvf5iugCNzQssTJp9LjDPHAcmCqUw==", + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, "dependencies": { - "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1", - "@vue/babel-plugin-transform-vue-jsx": "^1.2.1", - "@vue/babel-sugar-composition-api-inject-h": "^1.3.0", - "@vue/babel-sugar-composition-api-render-instance": "^1.3.0", - "@vue/babel-sugar-functional-vue": "^1.2.2", - "@vue/babel-sugar-inject-h": "^1.2.2", - "@vue/babel-sugar-v-model": "^1.3.0", - "@vue/babel-sugar-v-on": "^1.3.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0", - "vue": "2.x" + "engines": { + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "vue": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@vue/babel-preset-app/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "call-bind": "^1.0.2" }, - "engines": { - "node": ">=10" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@vue/babel-sugar-composition-api-inject-h": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-composition-api-inject-h/-/babel-sugar-composition-api-inject-h-1.3.0.tgz", - "integrity": "sha512-pIDOutEpqbURdVw7xhgxmuDW8Tl+lTgzJZC5jdlUu0lY2+izT9kz3Umd/Tbu0U5cpCJ2Yhu87BZFBzWpS0Xemg==", + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "dev": true, - "dependencies": { - "@babel/plugin-syntax-jsx": "^7.2.0" + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@vue/babel-sugar-composition-api-render-instance": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-composition-api-render-instance/-/babel-sugar-composition-api-render-instance-1.3.0.tgz", - "integrity": "sha512-NYNnU2r7wkJLMV5p9Zj4pswmCs037O/N2+/Fs6SyX7aRFzXJRP1/2CZh5cIwQxWQajHXuCUd5mTb7DxoBVWyTg==", + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dev": true, "dependencies": { - "@babel/plugin-syntax-jsx": "^7.2.0" + "has-tostringtag": "^1.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@vue/babel-sugar-functional-vue": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-functional-vue/-/babel-sugar-functional-vue-1.2.2.tgz", - "integrity": "sha512-JvbgGn1bjCLByIAU1VOoepHQ1vFsroSA/QkzdiSs657V79q6OwEWLCQtQnEXD/rLTA8rRit4rMOhFpbjRFm82w==", + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dev": true, "dependencies": { - "@babel/plugin-syntax-jsx": "^7.2.0" + "has-symbols": "^1.0.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@vue/babel-sugar-inject-h": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-inject-h/-/babel-sugar-inject-h-1.2.2.tgz", - "integrity": "sha512-y8vTo00oRkzQTgufeotjCLPAvlhnpSkcHFEp60+LJUwygGcd5Chrpn5480AQp/thrxVm8m2ifAk0LyFel9oCnw==", + "node_modules/is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", "dev": true, "dependencies": { - "@babel/plugin-syntax-jsx": "^7.2.0" + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@vue/babel-sugar-v-model": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-model/-/babel-sugar-v-model-1.3.0.tgz", - "integrity": "sha512-zcsabmdX48JmxTObn3xmrvvdbEy8oo63DphVyA3WRYGp4SEvJRpu/IvZCVPl/dXLuob2xO/QRuncqPgHvZPzpA==", + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "dev": true, "dependencies": { - "@babel/plugin-syntax-jsx": "^7.2.0", - "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1", - "@vue/babel-plugin-transform-vue-jsx": "^1.2.1", - "camelcase": "^5.0.0", - "html-tags": "^2.0.0", - "svg-tags": "^1.0.0" + "call-bind": "^1.0.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@vue/babel-sugar-v-model/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/@vue/babel-sugar-v-model/node_modules/html-tags": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", - "integrity": "sha512-+Il6N8cCo2wB/Vd3gqy/8TZhTD3QvcVeQLCnZiGkGCH3JP28IgGAY41giccp2W4R3jfyJPAP318FQTa1yU7K7g==", + "node_modules/is-wsl/node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", "dev": true, + "bin": { + "is-docker": "cli.js" + }, "engines": { - "node": ">=4" - } - }, - "node_modules/@vue/babel-sugar-v-on": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-on/-/babel-sugar-v-on-1.3.0.tgz", - "integrity": "sha512-8VZgrS0G5bh7+Prj7oJkzg9GvhSPnuW5YT6MNaVAEy4uwxRLJ8GqHenaStfllChTao4XZ3EZkNtHB4Xbr/ePdA==", - "dev": true, - "dependencies": { - "@babel/plugin-syntax-jsx": "^7.2.0", - "@vue/babel-plugin-transform-vue-jsx": "^1.2.1", - "camelcase": "^5.0.0" + "node": ">=8" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@vue/babel-sugar-v-on/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, - "node_modules/@vue/cli-overlay": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@vue/cli-overlay/-/cli-overlay-5.0.8.tgz", - "integrity": "sha512-KmtievE/B4kcXp6SuM2gzsnSd8WebkQpg3XaB6GmFh1BJGRqa1UiW9up7L/Q67uOdTigHxr5Ar2lZms4RcDjwQ==", + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, - "node_modules/@vue/cli-plugin-babel": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-babel/-/cli-plugin-babel-5.0.8.tgz", - "integrity": "sha512-a4qqkml3FAJ3auqB2kN2EMPocb/iu0ykeELwed+9B1c1nQ1HKgslKMHMPavYx3Cd/QAx2mBD4hwKBqZXEI/CsQ==", + "node_modules/jiti": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.18.2.tgz", + "integrity": "sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==", "dev": true, - "dependencies": { - "@babel/core": "^7.12.16", - "@vue/babel-preset-app": "^5.0.8", - "@vue/cli-shared-utils": "^5.0.8", - "babel-loader": "^8.2.2", - "thread-loader": "^3.0.0", - "webpack": "^5.54.0" - }, - "peerDependencies": { - "@vue/cli-service": "^3.0.0 || ^4.0.0 || ^5.0.0-0" + "bin": { + "jiti": "bin/jiti.js" } }, - "node_modules/@vue/cli-plugin-eslint": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-eslint/-/cli-plugin-eslint-5.0.8.tgz", - "integrity": "sha512-d11+I5ONYaAPW1KyZj9GlrV/E6HZePq5L5eAF5GgoVdu6sxr6bDgEoxzhcS1Pk2eh8rn1MxG/FyyR+eCBj/CNg==", + "node_modules/js-beautify": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.9.tgz", + "integrity": "sha512-coM7xq1syLcMyuVGyToxcj2AlzhkDjmfklL8r0JgJ7A76wyGMpJ1oA35mr4APdYNO/o/4YY8H54NQIJzhMbhBg==", "dev": true, "dependencies": { - "@vue/cli-shared-utils": "^5.0.8", - "eslint-webpack-plugin": "^3.1.0", - "globby": "^11.0.2", - "webpack": "^5.54.0", - "yorkie": "^2.0.0" + "config-chain": "^1.1.13", + "editorconfig": "^1.0.3", + "glob": "^8.1.0", + "nopt": "^6.0.0" }, - "peerDependencies": { - "@vue/cli-service": "^3.0.0 || ^4.0.0 || ^5.0.0-0", - "eslint": ">=7.5.0" - } - }, - "node_modules/@vue/cli-plugin-router": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-router/-/cli-plugin-router-5.0.8.tgz", - "integrity": "sha512-Gmv4dsGdAsWPqVijz3Ux2OS2HkMrWi1ENj2cYL75nUeL+Xj5HEstSqdtfZ0b1q9NCce+BFB6QnHfTBXc/fCvMg==", - "dev": true, - "dependencies": { - "@vue/cli-shared-utils": "^5.0.8" + "bin": { + "css-beautify": "js/bin/css-beautify.js", + "html-beautify": "js/bin/html-beautify.js", + "js-beautify": "js/bin/js-beautify.js" }, - "peerDependencies": { - "@vue/cli-service": "^3.0.0 || ^4.0.0 || ^5.0.0-0" + "engines": { + "node": ">=12" } }, - "node_modules/@vue/cli-plugin-typescript": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-typescript/-/cli-plugin-typescript-5.0.8.tgz", - "integrity": "sha512-JKJOwzJshBqsmp4yLBexwVMebOZ4VGJgbnYvmHVxasJOStF2RxwyW28ZF+zIvASGdat4sAUuo/3mAQyVhm7JHg==", + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "dependencies": { - "@babel/core": "^7.12.16", - "@types/webpack-env": "^1.15.2", - "@vue/cli-shared-utils": "^5.0.8", - "babel-loader": "^8.2.2", - "fork-ts-checker-webpack-plugin": "^6.4.0", - "globby": "^11.0.2", - "thread-loader": "^3.0.0", - "ts-loader": "^9.2.5", - "webpack": "^5.54.0" - }, - "peerDependencies": { - "@vue/cli-service": "^3.0.0 || ^4.0.0 || ^5.0.0-0", - "cache-loader": "^4.1.0", - "typescript": ">=2", - "vue": "^2 || ^3.2.13", - "vue-template-compiler": "^2.0.0" + "argparse": "^2.0.1" }, - "peerDependenciesMeta": { - "cache-loader": { - "optional": true - }, - "vue-template-compiler": { - "optional": true - } + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@vue/cli-plugin-vuex": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-vuex/-/cli-plugin-vuex-5.0.8.tgz", - "integrity": "sha512-HSYWPqrunRE5ZZs8kVwiY6oWcn95qf/OQabwLfprhdpFWAGtLStShjsGED2aDpSSeGAskQETrtR/5h7VqgIlBA==", + "node_modules/jsdom": { + "version": "22.1.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-22.1.0.tgz", + "integrity": "sha512-/9AVW7xNbsBv6GfWho4TTNjEo9fe6Zhf9O7s0Fhhr3u+awPwAJMKwAMXnkk5vBxflqLW9hTHX/0cs+P3gW+cQw==", "dev": true, - "peerDependencies": { - "@vue/cli-service": "^3.0.0 || ^4.0.0 || ^5.0.0-0" - } - }, - "node_modules/@vue/cli-service": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@vue/cli-service/-/cli-service-5.0.8.tgz", - "integrity": "sha512-nV7tYQLe7YsTtzFrfOMIHc5N2hp5lHG2rpYr0aNja9rNljdgcPZLyQRb2YRivTHqTv7lI962UXFURcpStHgyFw==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.12.16", - "@soda/friendly-errors-webpack-plugin": "^1.8.0", - "@soda/get-current-script": "^1.0.2", - "@types/minimist": "^1.2.0", - "@vue/cli-overlay": "^5.0.8", - "@vue/cli-plugin-router": "^5.0.8", - "@vue/cli-plugin-vuex": "^5.0.8", - "@vue/cli-shared-utils": "^5.0.8", - "@vue/component-compiler-utils": "^3.3.0", - "@vue/vue-loader-v15": "npm:vue-loader@^15.9.7", - "@vue/web-component-wrapper": "^1.3.0", - "acorn": "^8.0.5", - "acorn-walk": "^8.0.2", - "address": "^1.1.2", - "autoprefixer": "^10.2.4", - "browserslist": "^4.16.3", - "case-sensitive-paths-webpack-plugin": "^2.3.0", - "cli-highlight": "^2.1.10", - "clipboardy": "^2.3.0", - "cliui": "^7.0.4", - "copy-webpack-plugin": "^9.0.1", - "css-loader": "^6.5.0", - "css-minimizer-webpack-plugin": "^3.0.2", - "cssnano": "^5.0.0", - "debug": "^4.1.1", - "default-gateway": "^6.0.3", - "dotenv": "^10.0.0", - "dotenv-expand": "^5.1.0", - "fs-extra": "^9.1.0", - "globby": "^11.0.2", - "hash-sum": "^2.0.0", - "html-webpack-plugin": "^5.1.0", - "is-file-esm": "^1.0.0", - "launch-editor-middleware": "^2.2.1", - "lodash.defaultsdeep": "^4.6.1", - "lodash.mapvalues": "^4.6.0", - "mini-css-extract-plugin": "^2.5.3", - "minimist": "^1.2.5", - "module-alias": "^2.2.2", - "portfinder": "^1.0.26", - "postcss": "^8.2.6", - "postcss-loader": "^6.1.1", - "progress-webpack-plugin": "^1.0.12", - "ssri": "^8.0.1", - "terser-webpack-plugin": "^5.1.1", - "thread-loader": "^3.0.0", - "vue-loader": "^17.0.0", - "vue-style-loader": "^4.1.3", - "webpack": "^5.54.0", - "webpack-bundle-analyzer": "^4.4.0", - "webpack-chain": "^6.5.1", - "webpack-dev-server": "^4.7.3", - "webpack-merge": "^5.7.3", - "webpack-virtual-modules": "^0.4.2", - "whatwg-fetch": "^3.6.2" - }, - "bin": { - "vue-cli-service": "bin/vue-cli-service.js" + "dependencies": { + "abab": "^2.0.6", + "cssstyle": "^3.0.0", + "data-urls": "^4.0.0", + "decimal.js": "^10.4.3", + "domexception": "^4.0.0", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.4", + "parse5": "^7.1.2", + "rrweb-cssom": "^0.6.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.2", + "w3c-xmlserializer": "^4.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^2.0.0", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^12.0.1", + "ws": "^8.13.0", + "xml-name-validator": "^4.0.0" }, "engines": { - "node": "^12.0.0 || >= 14.0.0" + "node": ">=16" }, "peerDependencies": { - "vue-template-compiler": "^2.0.0", - "webpack-sources": "*" + "canvas": "^2.5.0" }, "peerDependenciesMeta": { - "cache-loader": { - "optional": true - }, - "less-loader": { - "optional": true - }, - "pug-plain-loader": { - "optional": true - }, - "raw-loader": { - "optional": true - }, - "sass-loader": { - "optional": true - }, - "stylus-loader": { - "optional": true - }, - "vue-template-compiler": { - "optional": true - }, - "webpack-sources": { + "canvas": { "optional": true } } }, - "node_modules/@vue/cli-service/node_modules/ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-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/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "dependencies": { - "minipass": "^3.1.1" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" }, "engines": { - "node": ">= 8" + "node": ">= 0.8.0" } }, - "node_modules/@vue/cli-shared-utils": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@vue/cli-shared-utils/-/cli-shared-utils-5.0.8.tgz", - "integrity": "sha512-uK2YB7bBVuQhjOJF+O52P9yFMXeJVj7ozqJkwYE9PlMHL1LMHjtCYm4cSdOebuPzyP+/9p0BimM/OqxsevIopQ==", - "dev": true, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", "dependencies": { - "@achrinza/node-ipc": "^9.2.5", - "chalk": "^4.1.2", - "execa": "^1.0.0", - "joi": "^17.4.0", - "launch-editor": "^2.2.1", - "lru-cache": "^6.0.0", - "node-fetch": "^2.6.7", - "open": "^8.0.2", - "ora": "^5.3.0", - "read-pkg": "^5.1.1", - "semver": "^7.3.4", - "strip-ansi": "^6.0.0" + "immediate": "~3.0.5" } }, - "node_modules/@vue/cli-shared-utils/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=10" } }, - "node_modules/@vue/cli-shared-utils/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/lint-staged": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.0.1.tgz", + "integrity": "sha512-2IU5OWmCaxch0X0+IBF4/v7sutpB+F3qoXbro43pYjQTOo5wumckjxoxn47pQBqqBsCWrD5HnI2uG/zJA7isew==", + "dev": true, + "dependencies": { + "chalk": "5.3.0", + "commander": "11.1.0", + "debug": "4.3.4", + "execa": "8.0.1", + "lilconfig": "2.1.0", + "listr2": "7.0.1", + "micromatch": "4.0.5", + "pidtree": "0.6.0", + "string-argv": "0.3.2", + "yaml": "2.3.2" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" }, "engines": { - "node": ">=10" + "node": ">=18.12.0" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://opencollective.com/lint-staged" } }, - "node_modules/@vue/cli-shared-utils/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, "engines": { - "node": ">=7.0.0" + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@vue/cli-shared-utils/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@vue/cli-shared-utils/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/lint-staged/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", "dev": true, "engines": { - "node": ">=8" + "node": ">=16" } }, - "node_modules/@vue/cli-shared-utils/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "node_modules/lint-staged/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" }, "engines": { - "node": ">=10" + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/@vue/cli-shared-utils/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/lint-staged/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@vue/compiler-core": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.47.tgz", - "integrity": "sha512-p4D7FDnQb7+YJmO2iPEv0SQNeNzcbHdGByJDsT4lynf63AFkOTFN07HsiRSvjGo0QrxR/o3d0hUyNCUnBU2Tig==", - "dependencies": { - "@babel/parser": "^7.16.4", - "@vue/shared": "3.2.47", - "estree-walker": "^2.0.2", - "source-map": "^0.6.1" + "node_modules/lint-staged/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" } }, - "node_modules/@vue/compiler-dom": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.47.tgz", - "integrity": "sha512-dBBnEHEPoftUiS03a4ggEig74J2YBZ2UIeyfpcRM2tavgMWo4bsEfgCGsu+uJIL/vax9S+JztH8NmQerUo7shQ==", - "dependencies": { - "@vue/compiler-core": "3.2.47", - "@vue/shared": "3.2.47" + "node_modules/lint-staged/node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" } }, - "node_modules/@vue/compiler-sfc": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.47.tgz", - "integrity": "sha512-rog05W+2IFfxjMcFw10tM9+f7i/+FFpZJJ5XHX72NP9eC2uRD+42M3pYcQqDXVYoj74kHMSEdQ/WmCjt8JFksQ==", - "dependencies": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.47", - "@vue/compiler-dom": "3.2.47", - "@vue/compiler-ssr": "3.2.47", - "@vue/reactivity-transform": "3.2.47", - "@vue/shared": "3.2.47", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7", - "postcss": "^8.1.10", - "source-map": "^0.6.1" + "node_modules/lint-staged/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==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@vue/compiler-ssr": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.47.tgz", - "integrity": "sha512-wVXC+gszhulcMD8wpxMsqSOpvDZ6xKXSVWkf50Guf/S+28hTAXPDYRTbLQ3EDkOP5Xz/+SY37YiwDquKbJOgZw==", + "node_modules/listr2": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-7.0.1.tgz", + "integrity": "sha512-nz+7hwgbDp8eWNoDgzdl4hA/xDSLrNRzPu1TLgOYs6l5Y+Ma6zVWWy9Oyt9TQFONwKoSPoka3H50D3vD5EuNwg==", + "dev": true, "dependencies": { - "@vue/compiler-dom": "3.2.47", - "@vue/shared": "3.2.47" + "cli-truncate": "^3.1.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^5.0.1", + "rfdc": "^1.3.0", + "wrap-ansi": "^8.1.0" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@vue/component-compiler-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.3.0.tgz", - "integrity": "sha512-97sfH2mYNU+2PzGrmK2haqffDpVASuib9/w2/noxiFi31Z54hW+q3izKQXXQZSNhtiUpAI36uSuYepeBe4wpHQ==", + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", "dev": true, "dependencies": { - "consolidate": "^0.15.1", - "hash-sum": "^1.0.2", - "lru-cache": "^4.1.2", - "merge-source-map": "^1.1.0", - "postcss": "^7.0.36", - "postcss-selector-parser": "^6.0.2", - "source-map": "~0.6.1", - "vue-template-es2015-compiler": "^1.9.0" + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" }, - "optionalDependencies": { - "prettier": "^1.18.2 || ^2.0.0" + "engines": { + "node": ">=4" } }, - "node_modules/@vue/component-compiler-utils/node_modules/hash-sum": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", - "dev": true - }, - "node_modules/@vue/component-compiler-utils/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "node_modules/local-pkg": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz", + "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==", "dev": true, - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/@vue/component-compiler-utils/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true - }, - "node_modules/@vue/component-compiler-utils/node_modules/postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "dependencies": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=6.0.0" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@vue/component-compiler-utils/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "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/@vue/devtools-api": { - "version": "6.4.5", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.4.5.tgz", - "integrity": "sha512-JD5fcdIuFxU4fQyXUu3w2KpAJHzTVdN+p4iOX2lMWSHMOoQdMAcpFLZzm9Z/2nmsoZ1a96QEhZ26e50xLBsgOQ==" + "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/@vue/eslint-config-prettier": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-7.0.0.tgz", - "integrity": "sha512-/CTc6ML3Wta1tCe1gUeO0EYnVXfo3nJXsIhZ8WJr3sov+cGASr6yuiibJTL6lmIBm7GobopToOuB3B6AWyV0Iw==", + "node_modules/log-update": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-5.0.1.tgz", + "integrity": "sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw==", "dev": true, "dependencies": { - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-prettier": "^4.0.0" + "ansi-escapes": "^5.0.0", + "cli-cursor": "^4.0.0", + "slice-ansi": "^5.0.0", + "strip-ansi": "^7.0.1", + "wrap-ansi": "^8.0.1" }, - "peerDependencies": { - "eslint": ">= 7.28.0", - "prettier": ">= 2.0.0" + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@vue/eslint-config-typescript": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-10.0.0.tgz", - "integrity": "sha512-F94cL8ug3FaYXlCfU5/wiGjk1qeadmoBpRGAOBq+qre3Smdupa59dd6ZJrsfRODpsMPyTG7330juMDsUvpZ3Rw==", + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, - "dependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0", - "@typescript-eslint/parser": "^5.0.0", - "vue-eslint-parser": "^8.0.0" - }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=12" }, - "peerDependencies": { - "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0", - "eslint-plugin-vue": "^8.0.1" - } - }, - "node_modules/@vue/reactivity": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.47.tgz", - "integrity": "sha512-7khqQ/75oyyg+N/e+iwV6lpy1f5wq759NdlS1fpAhFXa8VeAIKGgk2E/C4VF59lx5b+Ezs5fpp/5WsRYXQiKxQ==", - "dependencies": { - "@vue/shared": "3.2.47" + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@vue/reactivity-transform": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.47.tgz", - "integrity": "sha512-m8lGXw8rdnPVVIdIFhf0LeQ/ixyHkH5plYuS83yop5n7ggVJU+z5v0zecwEnX7fa7HNLBhh2qngJJkxpwEEmYA==", + "node_modules/log-update/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, "dependencies": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.47", - "@vue/shared": "3.2.47", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7" + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@vue/runtime-core": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.47.tgz", - "integrity": "sha512-RZxbLQIRB/K0ev0K9FXhNbBzT32H9iRtYbaXb0ZIz2usLms/D55dJR2t6cIEUn6vyhS3ALNvNthI+Q95C+NOpA==", + "node_modules/loupe": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", + "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "dev": true, "dependencies": { - "@vue/reactivity": "3.2.47", - "@vue/shared": "3.2.47" + "get-func-name": "^2.0.0" } }, - "node_modules/@vue/runtime-dom": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.47.tgz", - "integrity": "sha512-ArXrFTjS6TsDei4qwNvgrdmHtD930KgSKGhS5M+j8QxXrDJYLqYw4RRcDy1bz1m1wMmb6j+zGLifdVHtkXA7gA==", + "node_modules/magic-string": { + "version": "0.30.2", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.2.tgz", + "integrity": "sha512-lNZdu7pewtq/ZvWUp9Wpf/x7WzMTsR26TWV03BRZrXFsv+BI6dy8RAiKgm1uM/kyR0rCfUcqvOlXKG66KhIGug==", "dependencies": { - "@vue/runtime-core": "3.2.47", - "@vue/shared": "3.2.47", - "csstype": "^2.6.8" + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" } }, - "node_modules/@vue/server-renderer": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.47.tgz", - "integrity": "sha512-dN9gc1i8EvmP9RCzvneONXsKfBRgqFeFZLurmHOveL7oH6HiFXJw5OGu294n1nHc/HMgTy6LulU/tv5/A7f/LA==", - "dependencies": { - "@vue/compiler-ssr": "3.2.47", - "@vue/shared": "3.2.47" - }, - "peerDependencies": { - "vue": "3.2.47" + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" } }, - "node_modules/@vue/shared": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.47.tgz", - "integrity": "sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ==" + "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/@vue/test-utils": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.3.2.tgz", - "integrity": "sha512-hJnVaYhbrIm0yBS0+e1Y0Sj85cMyAi+PAbK4JHqMRUZ6S622Goa+G7QzkRSyvCteG8wop7tipuEbHoZo26wsSA==", + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, - "dependencies": { - "js-beautify": "1.14.6" - }, - "optionalDependencies": { - "@vue/compiler-dom": "^3.0.1", - "@vue/server-renderer": "^3.0.1" - }, - "peerDependencies": { - "@vue/compiler-dom": "^3.0.1", - "@vue/server-renderer": "^3.0.1", - "vue": "^3.0.1" + "engines": { + "node": ">= 8" } }, - "node_modules/@vue/vue-loader-v15": { - "name": "vue-loader", - "version": "15.9.8", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.8.tgz", - "integrity": "sha512-GwSkxPrihfLR69/dSV3+5CdMQ0D+jXg8Ma1S4nQXKJAznYFX14vHdc/NetQc34Dw+rBbIJyP7JOuVb9Fhprvog==", + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "dependencies": { - "@vue/component-compiler-utils": "^3.1.0", - "hash-sum": "^1.0.2", - "loader-utils": "^1.1.0", - "vue-hot-reload-api": "^2.3.0", - "vue-style-loader": "^4.1.0" - }, - "peerDependencies": { - "css-loader": "*", - "webpack": "^3.0.0 || ^4.1.0 || ^5.0.0-0" + "braces": "^3.0.2", + "picomatch": "^2.3.1" }, - "peerDependenciesMeta": { - "cache-loader": { - "optional": true - }, - "vue-template-compiler": { - "optional": true - } + "engines": { + "node": ">=8.6" } }, - "node_modules/@vue/vue-loader-v15/node_modules/hash-sum": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", - "dev": true - }, - "node_modules/@vue/vue3-jest": { - "version": "29.2.3", - "resolved": "https://registry.npmjs.org/@vue/vue3-jest/-/vue3-jest-29.2.3.tgz", - "integrity": "sha512-wbit0rGgy9ARUBtc5dZ6PGCrxazCPs5pZ6ycB0qYMoEPmkRj8lIVUfJmTz03ryIAeVQOcTKnEWdcqgrTErl3vg==", + "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==", "dev": true, - "dependencies": { - "@babel/plugin-transform-modules-commonjs": "^7.2.0", - "chalk": "^2.1.0", - "convert-source-map": "^1.6.0", - "css-tree": "^2.0.1", - "source-map": "0.5.6", - "tsconfig": "^7.0.0" - }, "engines": { - "node": ">10" - }, - "peerDependencies": { - "@babel/core": "7.x", - "babel-jest": "29.x", - "jest": "29.x", - "typescript": ">= 4.3", - "vue": "^3.0.0-0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">= 0.6" } }, - "node_modules/@vue/vue3-jest/node_modules/css-tree": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", - "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "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==", "dev": true, "dependencies": { - "mdn-data": "2.0.30", - "source-map-js": "^1.0.1" + "mime-db": "1.52.0" }, "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + "node": ">= 0.6" } }, - "node_modules/@vue/vue3-jest/node_modules/mdn-data": { - "version": "2.0.30", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", - "dev": true - }, - "node_modules/@vue/vue3-jest/node_modules/source-map": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", - "integrity": "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==", + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "dev": true, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@vue/web-component-wrapper": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@vue/web-component-wrapper/-/web-component-wrapper-1.3.0.tgz", - "integrity": "sha512-Iu8Tbg3f+emIIMmI2ycSI8QcEuAUgPTgHwesDU1eKMLE4YC/c/sFbGc70QgMq31ijRftV0R7vCm9co6rldCeOA==", - "dev": true - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", - "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", - "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==" - }, - "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==" - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", - "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==" - }, - "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==", - "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==" - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", - "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dependencies": { - "@xtuc/ieee754": "^1.2.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "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": { - "@xtuc/long": "4.2.2" + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "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==" + "node_modules/mitt": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-2.1.0.tgz", + "integrity": "sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg==" }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", - "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "node_modules/mlly": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.4.2.tgz", + "integrity": "sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg==", + "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-opt": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6", - "@webassemblyjs/wast-printer": "1.11.6" + "acorn": "^8.10.0", + "pathe": "^1.1.1", + "pkg-types": "^1.0.3", + "ufo": "^1.3.0" } }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", - "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", - "dependencies": { - "@webassemblyjs/ast": "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/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/@webassemblyjs/wasm-opt": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", - "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6" - } + "node_modules/muggle-string": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.3.1.tgz", + "integrity": "sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==", + "dev": true }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", - "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@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" + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" } }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", - "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@xtuc/long": "4.2.2" + "node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "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==" - }, - "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==" - }, - "node_modules/abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "node_modules/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/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "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/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } + "node_modules/node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "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==", + "node_modules/nopt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", "dev": true, "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "abbrev": "^1.0.0" }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", "bin": { - "acorn": "bin/acorn" + "nopt": "bin/nopt.js" }, "engines": { - "node": ">=0.4.0" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/acorn-globals": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", - "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", + "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": { - "acorn": "^8.1.0", - "acorn-walk": "^8.0.2" - } - }, - "node_modules/acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "peerDependencies": { - "acorn": "^8" + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "bin": { + "semver": "bin/semver" } }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, "engines": { - "node": ">=0.4.0" + "node": ">=0.10.0" } }, - "node_modules/address": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz", - "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==", + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", "dev": true, "engines": { - "node": ">= 0.12.0" + "node": ">=0.10.0" } }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "node_modules/npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", "dev": true, "dependencies": { - "debug": "4" + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" }, "engines": { - "node": ">= 6.0.0" + "node": ">= 4" } }, - "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==", + "node_modules/npm-run-all/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" + "color-convert": "^1.9.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "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": ">=4" } }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "node_modules/npm-run-all/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } + "engines": { + "node": ">=4" } }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", + "node_modules/npm-run-all/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": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "color-name": "1.1.3" } }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "node_modules/npm-run-all/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/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "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==", + "node_modules/npm-run-all/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": { - "type-fest": "^0.21.3" + "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": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4.8" } }, - "node_modules/ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "node_modules/npm-run-all/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "engines": [ - "node >= 0.8.0" - ], - "bin": { - "ansi-html": "bin/ansi-html" + "engines": { + "node": ">=0.8.0" } }, - "node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "node_modules/npm-run-all/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": ">=4" } }, - "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==", + "node_modules/npm-run-all/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, - "dependencies": { - "color-convert": "^1.9.0" - }, "engines": { "node": ">=4" } }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", - "dev": true - }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "node_modules/npm-run-all/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" + "bin": { + "semver": "bin/semver" } }, - "node_modules/arch": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", - "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/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-flatten": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", - "dev": true - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "node_modules/npm-run-all/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "dependencies": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/asn1.js/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/assert": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz", - "integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==", "dependencies": { - "es6-object-assign": "^1.1.0", - "is-nan": "^1.2.1", - "object-is": "^1.0.1", - "util": "^0.12.0" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, + "shebang-regex": "^1.0.0" + }, "engines": { - "node": ">=8" - } - }, - "node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, - "dependencies": { - "lodash": "^4.17.14" + "node": ">=0.10.0" } }, - "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 - }, - "node_modules/at-least-node": { + "node_modules/npm-run-all/node_modules/shebang-regex": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", "dev": true, "engines": { - "node": ">= 4.0.0" + "node": ">=0.10.0" } }, - "node_modules/autoprefixer": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.2.tgz", - "integrity": "sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==", + "node_modules/npm-run-all/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "dependencies": { - "browserslist": "^4.19.1", - "caniuse-lite": "^1.0.30001297", - "fraction.js": "^4.1.2", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" + "has-flag": "^3.0.0" }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=4" } }, - "node_modules/babel-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.5.0.tgz", - "integrity": "sha512-mA4eCDh5mSo2EcA9xQjVTpmbbNk32Zb3Q3QFQsNhaK56Q+yoXowzFodLux30HRgyOho5rsQ6B0P9QpMkvvnJ0Q==", + "node_modules/npm-run-all/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": { - "@jest/transform": "^29.5.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.5.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "isexe": "^2.0.0" }, - "peerDependencies": { - "@babel/core": "^7.8.0" + "bin": { + "which": "bin/which" } }, - "node_modules/babel-jest/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "path-key": "^4.0.0" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/babel-jest/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/babel-jest/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "boolbase": "^1.0.0" }, - "engines": { - "node": ">=7.0.0" + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "node_modules/babel-jest/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "node_modules/nwsapi": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.5.tgz", + "integrity": "sha512-6xpotnECFy/og7tKSBVmUNft7J3jyXAka4XvG6AUhFWRz+Q/Ljus7znJAA3bxColfQLdS+XsjoodtJfCgeTEFQ==", "dev": true }, - "node_modules/babel-jest/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "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": ">=8" + "node": ">=0.10.0" } }, - "node_modules/babel-jest/node_modules/slash": { + "node_modules/object-hash": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", "dev": true, "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/babel-jest/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/babel-loader": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz", - "integrity": "sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q==", + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, - "dependencies": { - "find-cache-dir": "^3.3.1", - "loader-utils": "^2.0.0", - "make-dir": "^3.1.0", - "schema-utils": "^2.6.5" - }, "engines": { - "node": ">= 8.9" - }, - "peerDependencies": { - "@babel/core": "^7.0.0", - "webpack": ">=2" + "node": ">= 0.4" } }, - "node_modules/babel-loader/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==", + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", "dev": true, "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" }, "engines": { - "node": ">=8.9.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "dependencies": { - "object.assign": "^4.1.0" + "wrappy": "1" } }, - "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==", + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "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" + "mimic-fn": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/babel-plugin-jest-hoist": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz", - "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==", + "node_modules/open": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", + "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", "dev": true, "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" + "default-browser": "^4.0.0", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^2.2.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz", - "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==", + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.13.11", - "@babel/helper-define-polyfill-provider": "^0.3.1", - "semver": "^6.1.1" + "@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" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz", - "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==", + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.1", - "core-js-compat": "^3.21.0" + "yocto-queue": "^0.1.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz", - "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/babel-preset-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz", - "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==", + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "dependencies": { - "babel-plugin-jest-hoist": "^29.5.0", - "babel-preset-current-node-syntax": "^1.0.0" + "p-limit": "^3.0.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", - "dev": true + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" }, - "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==", + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, "engines": { - "node": "*" + "node": ">=6" } }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", "dev": true, "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/bl/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, "engines": { - "node": ">= 6" + "node": ">=8" } }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" - }, - "node_modules/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.7", - "raw-body": "2.4.3", - "type-is": "~1.6.18" - }, "engines": { - "node": ">= 0.8" + "node": ">=0.10.0" } }, - "node_modules/body-parser/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "engines": { - "node": ">= 0.8" + "node": ">=8" } }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "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-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, - "dependencies": { - "ms": "2.0.0" + "engines": { + "node": ">=8" } }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "node_modules/pathe": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.1.tgz", + "integrity": "sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==", "dev": true }, - "node_modules/bonjour": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", - "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true, - "dependencies": { - "array-flatten": "^2.1.0", - "deep-equal": "^1.0.1", - "dns-equal": "^1.0.0", - "dns-txt": "^2.0.2", - "multicast-dns": "^6.0.1", - "multicast-dns-service-types": "^1.1.0" + "engines": { + "node": "*" } }, - "node_modules/boolbase": { + "node_modules/picocolors": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, - "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==", + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "node_modules/pidtree": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", "dev": true, - "dependencies": { - "fill-range": "^7.0.1" + "bin": { + "pidtree": "bin/pidtree.js" }, "engines": { - "node": ">=8" + "node": ">=0.10" } }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" - }, - "node_modules/browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dependencies": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" } }, - "node_modules/browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "node_modules/pinia": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.1.7.tgz", + "integrity": "sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==", "dependencies": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" + "@vue/devtools-api": "^6.5.0", + "vue-demi": ">=0.14.5" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "@vue/composition-api": "^1.4.0", + "typescript": ">=4.4.4", + "vue": "^2.6.14 || ^3.3.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + }, + "typescript": { + "optional": true + } } }, - "node_modules/browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dependencies": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" + "node_modules/pinia/node_modules/vue-demi": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.5.tgz", + "integrity": "sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } } }, - "node_modules/browserify-rsa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", - "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", - "dependencies": { - "bn.js": "^5.0.0", - "randombytes": "^2.0.1" + "node_modules/pirates": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "dev": true, + "engines": { + "node": ">= 6" } }, - "node_modules/browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "node_modules/pkg-types": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz", + "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==", + "dev": true, "dependencies": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" + "jsonc-parser": "^3.2.0", + "mlly": "^1.2.0", + "pathe": "^1.1.0" } }, - "node_modules/browserify-sign/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "node_modules/playwright": { + "version": "1.38.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.38.1.tgz", + "integrity": "sha512-oRMSJmZrOu1FP5iu3UrCx8JEFRIMxLDM0c/3o4bpzU5Tz97BypefWf7TuTNPWeCe279TPal5RtPPZ+9lW/Qkow==", + "dev": true, "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "playwright-core": "1.38.1" + }, + "bin": { + "playwright": "cli.js" }, "engines": { - "node": ">= 6" + "node": ">=16" + }, + "optionalDependencies": { + "fsevents": "2.3.2" } }, - "node_modules/browserify-sign/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dependencies": { - "pako": "~1.0.5" + "node_modules/playwright-core": { + "version": "1.38.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.38.1.tgz", + "integrity": "sha512-tQqNFUKa3OfMf4b2jQ7aGLB8o9bS3bOY0yMEtldtC2+spf8QXG9zvXLTXUeRsoNuxEYMgLYR+NXfAa1rjKRcrg==", + "dev": true, + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=16" } }, - "node_modules/browserslist": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.1.tgz", - "integrity": "sha512-Nq8MFCSrnJXSc88yliwlzQe3qNe3VntIjhsArW9IJOEPSHNx23FalwApUVbzAWABLhYJJ7y8AynWI/XM8OdfjQ==", + "node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "funding": [ { "type": "opencollective", - "url": "https://opencollective.com/browserslist" + "url": "https://opencollective.com/postcss/" }, { "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "caniuse-lite": "^1.0.30001359", - "electron-to-chromium": "^1.4.172", - "node-releases": "^2.0.5", - "update-browserslist-db": "^1.0.4" - }, - "bin": { - "browserslist": "cli.js" + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "node": "^10 || ^12 || >=14" } }, - "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==", + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", "dev": true, "dependencies": { - "fast-json-stable-stringify": "2.x" + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" }, "engines": { - "node": ">= 6" + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" } }, - "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==", + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", "dev": true, "dependencies": { - "node-int64": "^0.4.0" + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" } }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "node_modules/postcss-load-config": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz", + "integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" + "dependencies": { + "lilconfig": "^2.0.5", + "yaml": "^2.1.1" + }, + "engines": { + "node": ">= 14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true }, - { - "type": "consulting", - "url": "https://feross.org/support" + "ts-node": { + "optional": true } - ], + } + }, + "node_modules/postcss-nested": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", + "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", + "dev": true, "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "postcss-selector-parser": "^6.0.11" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + "node_modules/postcss-selector-parser": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } }, - "node_modules/buffer-indexof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", - "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true }, - "node_modules/buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==" - }, - "node_modules/builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==" + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } }, - "node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "node_modules/prettier": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", + "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, "engines": { - "node": ">= 0.8" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "fast-diff": "^1.1.2" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=6.0.0" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "node_modules/prettier-plugin-tailwindcss": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.5.6.tgz", + "integrity": "sha512-2Xgb+GQlkPAUCFi3sV+NOYcSI5XgduvDBL2Zt/hwJudeKXkyvRS65c38SB0yb9UB40+1rL83I6m0RtlOQ8eHdg==", "dev": true, "engines": { - "node": ">=6" + "node": ">=14.21.3" + }, + "peerDependencies": { + "@ianvs/prettier-plugin-sort-imports": "*", + "@prettier/plugin-pug": "*", + "@shopify/prettier-plugin-liquid": "*", + "@shufo/prettier-plugin-blade": "*", + "@trivago/prettier-plugin-sort-imports": "*", + "prettier": "^3.0", + "prettier-plugin-astro": "*", + "prettier-plugin-css-order": "*", + "prettier-plugin-import-sort": "*", + "prettier-plugin-jsdoc": "*", + "prettier-plugin-organize-attributes": "*", + "prettier-plugin-organize-imports": "*", + "prettier-plugin-style-order": "*", + "prettier-plugin-svelte": "*" + }, + "peerDependenciesMeta": { + "@ianvs/prettier-plugin-sort-imports": { + "optional": true + }, + "@prettier/plugin-pug": { + "optional": true + }, + "@shopify/prettier-plugin-liquid": { + "optional": true + }, + "@shufo/prettier-plugin-blade": { + "optional": true + }, + "@trivago/prettier-plugin-sort-imports": { + "optional": true + }, + "prettier-plugin-astro": { + "optional": true + }, + "prettier-plugin-css-order": { + "optional": true + }, + "prettier-plugin-import-sort": { + "optional": true + }, + "prettier-plugin-jsdoc": { + "optional": true + }, + "prettier-plugin-marko": { + "optional": true + }, + "prettier-plugin-organize-attributes": { + "optional": true + }, + "prettier-plugin-organize-imports": { + "optional": true + }, + "prettier-plugin-style-order": { + "optional": true + }, + "prettier-plugin-svelte": { + "optional": true + }, + "prettier-plugin-twig-melody": { + "optional": true + } } }, - "node_modules/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/camel-case/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "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/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true + }, + "node_modules/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/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "dev": true, - "dependencies": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" + "engines": { + "node": ">=6" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001361", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001361.tgz", - "integrity": "sha512-ybhCrjNtkFji1/Wto6SSJKkWk6kZgVQsDq5QI83SafsF6FXv2JB4df9eEdH6g8sdGgqTXrFLjAxqBGgYoU3azQ==", + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, "funding": [ { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" + "type": "github", + "url": "https://github.com/sponsors/feross" }, { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" } ] }, - "node_modules/case-sensitive-paths-webpack-plugin": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", - "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", + "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==", + "dev": true + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/read-cache/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "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==", + "node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" }, "engines": { "node": ">=4" } }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "node_modules/read-pkg/node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, "engines": { - "node": ">=10" + "node": ">=4" } }, - "node_modules/chart.js": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.9.1.tgz", - "integrity": "sha512-Ro2JbLmvg83gXF5F4sniaQ+lTbSv18E+TIf2cOeiH1Iqd2PGFOtem+DUufMZsCJwFE7ywPOpfXFBwRTGq7dh6w==" - }, - "node_modules/chartjs-plugin-datalabels": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/chartjs-plugin-datalabels/-/chartjs-plugin-datalabels-2.2.0.tgz", - "integrity": "sha512-14ZU30lH7n89oq+A4bWaJPnAG8a7ZTk7dKf48YAzMvJjQtjrgg5Dpk9f+LbjCF6bpx3RAGTeL13IXpKQYyRvlw==", - "peerDependencies": { - "chart.js": ">=3.0.0" + "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==", + "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/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "picomatch": "^2.2.1" }, "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "node": ">=8.10.0" } }, - "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==", + "node_modules/regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", "dev": true, "dependencies": { - "is-glob": "^4.0.1" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" }, "engines": { - "node": ">= 6" - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "engines": { - "node": ">=6.0" - } - }, - "node_modules/ci-info": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", - "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", - "dev": true - }, - "node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/cjs-module-lexer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", + "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/clean-css": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.2.4.tgz", - "integrity": "sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg==", + "node_modules/resolve": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", "dev": true, "dependencies": { - "source-map": "~0.6.0" + "is-core-module": "^2.11.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" }, - "engines": { - "node": ">= 10.0" + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", "dev": true, "dependencies": { - "restore-cursor": "^3.1.0" + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" }, "engines": { - "node": ">=8" - } - }, - "node_modules/cli-highlight": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", - "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "highlight.js": "^10.7.1", - "mz": "^2.4.0", - "parse5": "^5.1.1", - "parse5-htmlparser2-tree-adapter": "^6.0.0", - "yargs": "^16.0.0" - }, - "bin": { - "highlight": "bin/highlight" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, - "engines": { - "node": ">=8.0.0", - "npm": ">=5.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-highlight/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/restore-cursor/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, - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=6" } }, - "node_modules/cli-highlight/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/restore-cursor/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": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "mimic-fn": "^2.1.0" }, "engines": { - "node": ">=10" + "node": ">=6" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-highlight/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, "engines": { - "node": ">=7.0.0" + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, - "node_modules/cli-highlight/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", "dev": true }, - "node_modules/cli-highlight/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-highlight/node_modules/highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/cli-highlight/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/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "glob": "^7.1.3" }, - "engines": { - "node": ">=8" + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/cli-spinners": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", - "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "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==", "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": ">=6" + "node": "*" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/cli-truncate": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", - "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "node_modules/rollup": { + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.28.0.tgz", + "integrity": "sha512-d7zhvo1OUY2SXSM6pfNjgD5+d0Nz87CUp4mt8l/GgVP3oBsPwzNvSzyu1me6BSG9JIgWNTVcafIXBIyM8yQ3yw==", "dev": true, - "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" + "bin": { + "rollup": "dist/bin/rollup" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=14.18.0", + "npm": ">=8.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "node_modules/cli-truncate/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==", + "node_modules/rrweb-cssom": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", + "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==", "dev": true }, - "node_modules/cli-truncate/node_modules/string-width": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.0.tgz", - "integrity": "sha512-7x54QnN21P+XL/v8SuNKvfgsUre6PXpN7mc77N3HlZv+f1SBRGmjxtOud2Z6FZ8DmdkD/IdjCaf9XXbnqmTZGQ==", + "node_modules/run-applescript": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", + "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", "dev": true, "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "execa": "^5.0.0" }, "engines": { "node": ">=12" @@ -6135,247 +5446,99 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-truncate/node_modules/strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "node_modules/run-applescript/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "dependencies": { - "ansi-regex": "^6.0.1" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" }, "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/clipboardy": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz", - "integrity": "sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==", + "node_modules/run-applescript/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, - "dependencies": { - "arch": "^2.1.1", - "execa": "^1.0.0", - "is-wsl": "^2.1.1" - }, "engines": { - "node": ">=8" + "node": ">=10.17.0" } }, - "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==", + "node_modules/run-applescript/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, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "node_modules/run-applescript/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": ">=0.8" + "node": ">=6" } }, - "node_modules/clone-deep": { + "node_modules/run-applescript/node_modules/npm-run-path": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" + "path-key": "^3.0.0" }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "node_modules/run-applescript/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": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", - "dev": true - }, - "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/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/colord": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.2.tgz", - "integrity": "sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==", - "dev": true - }, - "node_modules/colorette": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", - "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", - "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, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "node_modules/compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, - "dependencies": { - "mime-db": ">= 1.43.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, - "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/compression/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/compression/node_modules/ms": { + "node_modules/run-applescript/node_modules/strip-final-newline": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "node_modules/config-chain": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", - "dev": true, - "dependencies": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "node_modules/connect-history-api-fallback": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", - "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, "engines": { - "node": ">=0.8" + "node": ">=6" } }, - "node_modules/console-browserify": { + "node_modules/run-parallel": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", - "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" - }, - "node_modules/consolidate": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz", - "integrity": "sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==", - "dev": true, - "dependencies": { - "bluebird": "^3.1.1" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==" - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-disposition/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "funding": [ { @@ -6387,26015 +5550,1391 @@ "url": "https://www.patreon.com/feross" }, { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true - }, - "node_modules/copy-webpack-plugin": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-9.1.0.tgz", - "integrity": "sha512-rxnR7PaGigJzhqETHGmAcxKnLZSR5u1Y3/bcIv/1FnqXedcL/E2ewK7ZCNrArJKCiSv8yVXhTqetJh8inDvfsA==", - "dev": true, - "dependencies": { - "fast-glob": "^3.2.7", - "glob-parent": "^6.0.1", - "globby": "^11.0.3", - "normalize-path": "^3.0.0", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - } - }, - "node_modules/copy-webpack-plugin/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/core-js": { - "version": "3.29.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.29.1.tgz", - "integrity": "sha512-+jwgnhg6cQxKYIIjGtAHq2nwUOolo9eoFZ4sHfUH09BLXBgxnH4gA0zEd+t+BO2cNB8idaBtZFcFTRjQJRJmAw==", - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-js-compat": { - "version": "3.23.4", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.23.4.tgz", - "integrity": "sha512-RkSRPe+JYEoflcsuxJWaiMPhnZoFS51FcIxm53k4KzhISCBTmaGlto9dTIrYuk0hnJc3G6pKufAKepHnBq6B6Q==", - "dev": true, - "dependencies": { - "browserslist": "^4.21.1", - "semver": "7.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-js-compat/node_modules/semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "node_modules/cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", - "dev": true, - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/create-ecdh": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", - "dependencies": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" - } - }, - "node_modules/create-ecdh/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "node_modules/create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dependencies": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/cross-spawn/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dependencies": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - }, - "engines": { - "node": "*" - } - }, - "node_modules/css-declaration-sorter": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.1.4.tgz", - "integrity": "sha512-lpfkqS0fctcmZotJGhnxkIyJWvBXgpyi2wsFd4J8VB7wzyrT6Ch/3Q+FMNJpjK4gu1+GN5khOnpU2ZVKrLbhCw==", - "dev": true, - "dependencies": { - "timsort": "^0.3.0" - }, - "engines": { - "node": ">= 10" - }, - "peerDependencies": { - "postcss": "^8.0.9" - } - }, - "node_modules/css-loader": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.6.0.tgz", - "integrity": "sha512-FK7H2lisOixPT406s5gZM1S3l8GrfhEBT3ZiL2UX1Ng1XWs0y2GPllz/OTyvbaHe12VgQrIXIzuEGVlbUhodqg==", - "dev": true, - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.5", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.3.5" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/css-loader/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/css-minimizer-webpack-plugin": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz", - "integrity": "sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==", - "dev": true, - "dependencies": { - "cssnano": "^5.0.6", - "jest-worker": "^27.0.2", - "postcss": "^8.3.5", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@parcel/css": { - "optional": true - }, - "clean-css": { - "optional": true - }, - "csso": { - "optional": true - }, - "esbuild": { - "optional": true - } - } - }, - "node_modules/css-minimizer-webpack-plugin/node_modules/ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/css-minimizer-webpack-plugin/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/css-minimizer-webpack-plugin/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/css-minimizer-webpack-plugin/node_modules/schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/css-select": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz", - "integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^5.1.0", - "domhandler": "^4.3.0", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "dev": true, - "dependencies": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/css-what": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", - "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==", - "dev": true, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cssnano": { - "version": "5.0.17", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.0.17.tgz", - "integrity": "sha512-fmjLP7k8kL18xSspeXTzRhaFtRI7DL9b8IcXR80JgtnWBpvAzHT7sCR/6qdn0tnxIaINUN6OEQu83wF57Gs3Xw==", - "dev": true, - "dependencies": { - "cssnano-preset-default": "^5.1.12", - "lilconfig": "^2.0.3", - "yaml": "^1.10.2" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/cssnano" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/cssnano-preset-default": { - "version": "5.1.12", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.1.12.tgz", - "integrity": "sha512-rO/JZYyjW1QNkWBxMGV28DW7d98UDLaF759frhli58QFehZ+D/LSmwQ2z/ylBAe2hUlsIWTq6NYGfQPq65EF9w==", - "dev": true, - "dependencies": { - "css-declaration-sorter": "^6.0.3", - "cssnano-utils": "^3.0.2", - "postcss-calc": "^8.2.0", - "postcss-colormin": "^5.2.5", - "postcss-convert-values": "^5.0.4", - "postcss-discard-comments": "^5.0.3", - "postcss-discard-duplicates": "^5.0.3", - "postcss-discard-empty": "^5.0.3", - "postcss-discard-overridden": "^5.0.4", - "postcss-merge-longhand": "^5.0.6", - "postcss-merge-rules": "^5.0.6", - "postcss-minify-font-values": "^5.0.4", - "postcss-minify-gradients": "^5.0.6", - "postcss-minify-params": "^5.0.5", - "postcss-minify-selectors": "^5.1.3", - "postcss-normalize-charset": "^5.0.3", - "postcss-normalize-display-values": "^5.0.3", - "postcss-normalize-positions": "^5.0.4", - "postcss-normalize-repeat-style": "^5.0.4", - "postcss-normalize-string": "^5.0.4", - "postcss-normalize-timing-functions": "^5.0.3", - "postcss-normalize-unicode": "^5.0.4", - "postcss-normalize-url": "^5.0.5", - "postcss-normalize-whitespace": "^5.0.4", - "postcss-ordered-values": "^5.0.5", - "postcss-reduce-initial": "^5.0.3", - "postcss-reduce-transforms": "^5.0.4", - "postcss-svgo": "^5.0.4", - "postcss-unique-selectors": "^5.0.4" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/cssnano-utils": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.0.2.tgz", - "integrity": "sha512-KhprijuQv2sP4kT92sSQwhlK3SJTbDIsxcfIEySB0O+3m9esFOai7dP9bMx5enHAh2MwarVIcnwiWoOm01RIbQ==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", - "dev": true, - "dependencies": { - "css-tree": "^1.1.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/cssom": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", - "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", - "dev": true - }, - "node_modules/cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, - "dependencies": { - "cssom": "~0.3.6" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cssstyle/node_modules/cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - }, - "node_modules/csstype": { - "version": "2.6.19", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.19.tgz", - "integrity": "sha512-ZVxXaNy28/k3kJg0Fou5MiYpp88j7H9hLZp8PDC3jV0WFjfH5E9xHb56L0W59cPbKbcHXeP4qyT8PrHp8t6LcQ==" - }, - "node_modules/data-urls": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", - "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", - "dev": true, - "dependencies": { - "abab": "^2.0.6", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^11.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/data-urls/node_modules/tr46": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", - "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", - "dev": true, - "dependencies": { - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/data-urls/node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/data-urls/node_modules/whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", - "dev": true, - "dependencies": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "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, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "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/dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true - }, - "node_modules/deep-equal": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", - "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", - "dev": true, - "dependencies": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", - "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.2.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dev": true, - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/default-gateway/node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/default-gateway/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/default-gateway/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-gateway/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/default-gateway/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/default-gateway/node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/default-gateway/node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/default-gateway/node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/default-gateway/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "dependencies": { - "clone": "^1.0.2" - } - }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/del": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", - "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", - "dev": true, - "dependencies": { - "globby": "^11.0.1", - "graceful-fs": "^4.2.4", - "is-glob": "^4.0.1", - "is-path-cwd": "^2.2.0", - "is-path-inside": "^3.0.2", - "p-map": "^4.0.0", - "rimraf": "^3.0.2", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/des.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", - "dependencies": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, - "node_modules/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/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true - }, - "node_modules/diff-sequences": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", - "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dependencies": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } - }, - "node_modules/diffie-hellman/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dns-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", - "dev": true - }, - "node_modules/dns-packet": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz", - "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==", - "dev": true, - "dependencies": { - "ip": "^1.1.0", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/dns-txt": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", - "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", - "dev": true, - "dependencies": { - "buffer-indexof": "^1.0.0" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", - "dev": true, - "dependencies": { - "utila": "~0.4" - } - }, - "node_modules/dom-serializer": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", - "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", - "dev": true, - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domain-browser": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-4.22.0.tgz", - "integrity": "sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://bevry.me/fund" - } - }, - "node_modules/domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domexception": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", - "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", - "dev": true, - "dependencies": { - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/domexception/node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/domhandler": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz", - "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==", - "dev": true, - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/dot-case/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - }, - "node_modules/dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/dotenv-expand": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", - "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", - "dev": true - }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "node_modules/easy-stack": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/easy-stack/-/easy-stack-1.0.1.tgz", - "integrity": "sha512-wK2sCs4feiiJeFXn3zvY0p41mdU5VUgbgs1rNsc/y5ngFUijdWd+iIN8eoyuZHKB8xN6BL4PdWmzqFmxNg6V2w==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/editorconfig": { - "version": "0.15.3", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", - "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", - "dev": true, - "dependencies": { - "commander": "^2.19.0", - "lru-cache": "^4.1.5", - "semver": "^5.6.0", - "sigmund": "^1.0.1" - }, - "bin": { - "editorconfig": "bin/editorconfig" - } - }, - "node_modules/editorconfig/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/editorconfig/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/editorconfig/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/editorconfig/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "dev": true - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "node_modules/electron-to-chromium": { - "version": "1.4.176", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.176.tgz", - "integrity": "sha512-92JdgyRlcNDwuy75MjuFSb3clt6DGJ2IXSpg0MCjKd3JV9eSmuUAIyWiGAp/EtT0z2D4rqbYqThQLV90maH3Zw==" - }, - "node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.14.0.tgz", - "integrity": "sha512-+DCows0XNwLDcUhbFJPdlQEVnT2zXlCv7hPxemTz86/O+B/hCQ+mb7ydkPKiflpVraqLPCAfu7lDy+hBXueojw==", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/enhanced-resolve/node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/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/error-stack-parser": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.6.tgz", - "integrity": "sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ==", - "dev": true, - "dependencies": { - "stackframe": "^1.1.1" - } - }, - "node_modules/es-abstract": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", - "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", - "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "regexp.prototype.flags": "^1.4.3", - "string.prototype.trimend": "^1.0.5", - "string.prototype.trimstart": "^1.0.5", - "unbox-primitive": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-module-lexer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.2.1.tgz", - "integrity": "sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==" - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es6-object-assign": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", - "integrity": "sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==" - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "dev": true, - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/escodegen/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/escodegen/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz", - "integrity": "sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==", - "dev": true, - "dependencies": { - "@eslint/eslintrc": "^2.0.0", - "@eslint/js": "8.35.0", - "@humanwhocodes/config-array": "^0.11.8", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.4.0", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-prettier": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.4.0.tgz", - "integrity": "sha512-CFotdUcMY18nGRo5KGsnNxpznzhkopOcOo0InID+sgQssPrzjvsyKZPvOgymTFeHrFuC3Tzdf2YndhXtULK9Iw==", - "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-prettier": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", - "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", - "dev": true, - "dependencies": { - "prettier-linter-helpers": "^1.0.0" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "eslint": ">=7.28.0", - "prettier": ">=2.0.0" - }, - "peerDependenciesMeta": { - "eslint-config-prettier": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-vue": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-8.7.1.tgz", - "integrity": "sha512-28sbtm4l4cOzoO1LtzQPxfxhQABararUb1JtqusQqObJpWX2e/gmVyeYVfepizPFne0Q5cILkYGiBoV36L12Wg==", - "dev": true, - "dependencies": { - "eslint-utils": "^3.0.0", - "natural-compare": "^1.4.0", - "nth-check": "^2.0.1", - "postcss-selector-parser": "^6.0.9", - "semver": "^7.3.5", - "vue-eslint-parser": "^8.0.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/eslint-plugin-vue/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/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==", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint-webpack-plugin": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-3.1.1.tgz", - "integrity": "sha512-xSucskTN9tOkfW7so4EaiFIkulWLXwCB/15H917lR6pTv0Zot6/fetFucmENRb7J5whVSFKIvwnrnsa78SG2yg==", - "dev": true, - "dependencies": { - "@types/eslint": "^7.28.2", - "jest-worker": "^27.3.1", - "micromatch": "^4.0.4", - "normalize-path": "^3.0.0", - "schema-utils": "^3.1.1" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0", - "webpack": "^5.0.0" - } - }, - "node_modules/eslint-webpack-plugin/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/eslint/node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/globals": { - "version": "13.19.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", - "integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/espree": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", - "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", - "dev": true, - "dependencies": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "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, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/event-pubsub": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/event-pubsub/-/event-pubsub-4.3.0.tgz", - "integrity": "sha512-z7IyloorXvKbFx9Bpie2+vMJKKx1fH1EN5yiTfp8CiLOTptSYy1g8H4yDpGlEdshL1PBiFtBHepF2cNsqeEeFQ==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dependencies": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "dependencies": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", - "dev": true, - "dependencies": { - "@jest/expect-utils": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/express": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", - "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", - "dev": true, - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.19.2", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.4.2", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.9.7", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.17.2", - "serve-static": "1.14.2", - "setprototypeof": "1.2.0", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express/node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true - }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/express/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/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==" - }, - "node_modules/fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "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==" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dev": true, - "dependencies": { - "websocket-driver": ">=0.5.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/fb-watchman": { - "version": "2.0.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/figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/filter-obj": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-2.0.2.tgz", - "integrity": "sha512-lO3ttPjHZRfjMcxWKb1j1eDhTFsu4meeR3lnMcnBFhk6RuLhvEiuALu2TlfL310ph4lCYYwgF/ElIjdP739tdg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/find-cache-dir": { - "version": "3.3.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": "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/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", - "dev": true - }, - "node_modules/follow-redirects": { - "version": "1.14.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/fork-ts-checker-webpack-plugin": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz", - "integrity": "sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.8.3", - "@types/json-schema": "^7.0.5", - "chalk": "^4.1.0", - "chokidar": "^3.4.2", - "cosmiconfig": "^6.0.0", - "deepmerge": "^4.2.2", - "fs-extra": "^9.0.0", - "glob": "^7.1.6", - "memfs": "^3.1.2", - "minimatch": "^3.0.4", - "schema-utils": "2.7.0", - "semver": "^7.3.2", - "tapable": "^1.0.0" - }, - "engines": { - "node": ">=10", - "yarn": ">=1.0.0" - }, - "peerDependencies": { - "eslint": ">= 6", - "typescript": ">= 2.7", - "vue-template-compiler": "*", - "webpack": ">= 4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - }, - "vue-template-compiler": { - "optional": true - } - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", - "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.4", - "ajv": "^6.12.2", - "ajv-keywords": "^3.4.1" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fraction.js": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.3.tgz", - "integrity": "sha512-pUHWWt6vHzZZiQJcM6S/0PXfS+g6FM4BF5rj9wZyreivhQPdsh5PpE25VtSNxq80wHS5RfY51Ii+8Z0Zl/pmzg==", - "dev": true, - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://www.patreon.com/infusion" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/fs-monkey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", - "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gitart-vue-dialog": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/gitart-vue-dialog/-/gitart-vue-dialog-2.4.1.tgz", - "integrity": "sha512-eVYQiHhCRtw4fR7eCUbD4Sj3KDF8ZJt22We1SOkHsdbEAzjwqgjAiYAAgKcLT16FXMjURv8XSWDLU8VNL9Nf3A==", - "peerDependencies": { - "vue": "^3.2.6" - } - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/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==" - }, - "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/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", - "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" - }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, - "node_modules/gzip-size": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", - "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", - "dev": true, - "dependencies": { - "duplexer": "^0.1.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dependencies": { - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/hash-base/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/hash-base/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/hash-sum": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz", - "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==", - "dev": true - }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/highlight.js": { - "version": "11.7.0", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.7.0.tgz", - "integrity": "sha512-1rRqesRFhMO/PRF+G86evnyJkCgaZFOI+Z6kdj15TA18funfoqJXvgPCLSf0SWq3SRfg1j3HlDs8o4s3EGq1oQ==", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "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/hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - } - }, - "node_modules/html-encoding-sniffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", - "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", - "dev": true, - "dependencies": { - "whatwg-encoding": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/html-entities": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", - "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", - "dev": true - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", - "dev": true, - "dependencies": { - "camel-case": "^4.1.2", - "clean-css": "^5.2.2", - "commander": "^8.3.0", - "he": "^1.2.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.10.0" - }, - "bin": { - "html-minifier-terser": "cli.js" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/html-tags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz", - "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/html-webpack-plugin": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz", - "integrity": "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==", - "dev": true, - "dependencies": { - "@types/html-minifier-terser": "^6.0.0", - "html-minifier-terser": "^6.0.2", - "lodash": "^4.17.21", - "pretty-error": "^4.0.0", - "tapable": "^2.0.0" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/html-webpack-plugin" - }, - "peerDependencies": { - "webpack": "^5.20.0" - } - }, - "node_modules/html-webpack-plugin/node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "node_modules/http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", - "dev": true - }, - "node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "dev": true, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/http-parser-js": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.5.tgz", - "integrity": "sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA==", - "dev": true - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/http-proxy-middleware": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.3.tgz", - "integrity": "sha512-1bloEwnrHMnCoO/Gcwbz7eSVvW50KPES01PecpagI+YLNLci4AcuKJrujW4Mc3sBLpFxMSlsLNHS5Nl/lvrTPA==", - "dev": true, - "dependencies": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@types/express": "^4.17.13" - }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - } - } - }, - "node_modules/https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==" - }, - "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/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "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/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", - "dependencies": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true - }, - "node_modules/ipaddr.js": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", - "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-ci": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", - "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", - "dev": true, - "dependencies": { - "ci-info": "^1.5.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/is-core-module": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", - "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-file-esm": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-file-esm/-/is-file-esm-1.0.0.tgz", - "integrity": "sha512-rZlaNKb4Mr8WlRu2A9XdeoKgnO5aA53XdPHgCKVyCrQ/rWi89RET1+bq37Ru46obaQXeiX4vmFIm1vks41hoSA==", - "dev": true, - "dependencies": { - "read-pkg-up": "^7.0.1" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-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", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-nan": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", - "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz", - "integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==", - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.20.0", - "for-each": "^0.3.3", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "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/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", - "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/javascript-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-2.1.0.tgz", - "integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==", - "dev": true - }, - "node_modules/jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.5.0.tgz", - "integrity": "sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==", - "dev": true, - "dependencies": { - "@jest/core": "^29.5.0", - "@jest/types": "^29.5.0", - "import-local": "^3.0.2", - "jest-cli": "^29.5.0" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-changed-files": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", - "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", - "dev": true, - "dependencies": { - "execa": "^5.0.0", - "p-limit": "^3.1.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-changed-files/node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/jest-changed-files/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/jest-changed-files/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-changed-files/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-changed-files/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-changed-files/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-changed-files/node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-changed-files/node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-changed-files/node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-changed-files/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/jest-circus": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.5.0.tgz", - "integrity": "sha512-gq/ongqeQKAplVxqJmbeUOJJKkW3dDNPY8PjhJ5G0lBRvu0e3EWGxGy5cI4LAGA7gV2UHCtWBI4EMXK8c9nQKA==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^0.7.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.5.0", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.5.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-circus/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-circus/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-circus/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-circus/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-circus/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-circus/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-circus/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-circus/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-cli": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.5.0.tgz", - "integrity": "sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==", - "dev": true, - "dependencies": { - "@jest/core": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "import-local": "^3.0.2", - "jest-config": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "prompts": "^2.0.1", - "yargs": "^17.3.1" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-cli/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-cli/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-cli/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/jest-cli/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-cli/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-cli/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-cli/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-cli/node_modules/yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/jest-cli/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/jest-config": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.5.0.tgz", - "integrity": "sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.5.0", - "@jest/types": "^29.5.0", - "babel-jest": "^29.5.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.5.0", - "jest-environment-node": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.5.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/jest-config/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-config/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-config/node_modules/ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-config/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-config/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-config/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-config/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-config/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-diff": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", - "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.4.3", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-diff/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-diff/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-diff/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-diff/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-diff/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-diff/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-docblock": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz", - "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==", - "dev": true, - "dependencies": { - "detect-newline": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-each": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.5.0.tgz", - "integrity": "sha512-HM5kIJ1BTnVt+DQZ2ALp3rzXEl+g726csObrW/jpEGl+CDSSQpOJJX2KE/vEg8cxcMXdyEPu6U4QX5eruQv5hA==", - "dev": true, - "dependencies": { - "@jest/types": "^29.5.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", - "jest-util": "^29.5.0", - "pretty-format": "^29.5.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-each/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-each/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-each/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-each/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-each/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-each/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-environment-jsdom": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.5.0.tgz", - "integrity": "sha512-/KG8yEK4aN8ak56yFVdqFDzKNHgF4BAymCx2LbPNPsUshUlfAl0eX402Xm1pt+eoG9SLZEUVifqXtX8SK74KCw==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/jsdom": "^20.0.0", - "@types/node": "*", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0", - "jsdom": "^20.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/jest-environment-node": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.5.0.tgz", - "integrity": "sha512-ExxuIK/+yQ+6PRGaHkKewYtg6hto2uGCgvKdb2nfJfKXgZ17DfXjvbZ+jA1Qt9A8EQSfPnt5FKIfnOO3u1h9qw==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-get-type": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", - "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-haste-map": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.5.0.tgz", - "integrity": "sha512-IspOPnnBro8YfVYSw6yDRKh/TiCdRngjxeacCps1cQ9cgVN6+10JUcuJ1EabrgYLOATsIAigxA0rLR9x/YlrSA==", - "dev": true, - "dependencies": { - "@jest/types": "^29.5.0", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" - } - }, - "node_modules/jest-haste-map/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-haste-map/node_modules/jest-worker": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", - "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", - "dev": true, - "dependencies": { - "@types/node": "*", - "jest-util": "^29.5.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-haste-map/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/jest-leak-detector": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.5.0.tgz", - "integrity": "sha512-u9YdeeVnghBUtpN5mVxjID7KbkKE1QU4f6uUwuxiY0vYRi9BUCLKlPEZfDGR67ofdFmDz9oPAy2G92Ujrntmow==", - "dev": true, - "dependencies": { - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-matcher-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz", - "integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.5.0", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-matcher-utils/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-matcher-utils/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-matcher-utils/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-matcher-utils/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-matcher-utils/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-matcher-utils/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-message-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", - "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.5.0", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-message-util/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-message-util/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-message-util/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-message-util/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-message-util/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-message-util/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-message-util/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-mock": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.5.0.tgz", - "integrity": "sha512-GqOzvdWDE4fAV2bWQLQCkujxYWL7RxjCnj71b5VhDAGOevB3qj3Ovg26A5NI84ZpODxyzaozXLOh2NCgkbvyaw==", - "dev": true, - "dependencies": { - "@jest/types": "^29.5.0", - "@types/node": "*", - "jest-util": "^29.5.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "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" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } - } - }, - "node_modules/jest-regex-util": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz", - "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.5.0.tgz", - "integrity": "sha512-1TzxJ37FQq7J10jPtQjcc+MkCkE3GBpBecsSUWJ0qZNJpmg6m0D9/7II03yJulm3H/fvVjgqLh/k2eYg+ui52w==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve-dependencies": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.5.0.tgz", - "integrity": "sha512-sjV3GFr0hDJMBpYeUuGduP+YeCRbd7S/ck6IvL3kQ9cpySYKqcqhdLLC2rFwrcL7tz5vYibomBrsFYWkIGGjOg==", - "dev": true, - "dependencies": { - "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.5.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-resolve/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-resolve/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-resolve/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-resolve/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-resolve/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-resolve/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-runner": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.5.0.tgz", - "integrity": "sha512-m7b6ypERhFghJsslMLhydaXBiLf7+jXy8FwGRHO3BGV1mcQpPbwiqiKUR2zU2NJuNeMenJmlFZCsIqzJCTeGLQ==", - "dev": true, - "dependencies": { - "@jest/console": "^29.5.0", - "@jest/environment": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-leak-detector": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-resolve": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-util": "^29.5.0", - "jest-watcher": "^29.5.0", - "jest-worker": "^29.5.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runner/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-runner/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-runner/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-runner/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-runner/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-runner/node_modules/jest-worker": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", - "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", - "dev": true, - "dependencies": { - "@types/node": "*", - "jest-util": "^29.5.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runner/node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/jest-runner/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-runner/node_modules/source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/jest-runner/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-runtime": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.5.0.tgz", - "integrity": "sha512-1Hr6Hh7bAgXQP+pln3homOiEZtCDZFqwmle7Ew2j8OlbkIu6uE3Y/etJQG8MLQs3Zy90xrp2C0BRrtPHG4zryw==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/globals": "^29.5.0", - "@jest/source-map": "^29.4.3", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runtime/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-runtime/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-runtime/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-runtime/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-runtime/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-runtime/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-runtime/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-snapshot": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.5.0.tgz", - "integrity": "sha512-x7Wolra5V0tt3wRs3/ts3S6ciSQVypgGQlJpz2rsdQYoUKxMxPNaoHMGJN6qAuPJqS+2iQ1ZUn5kl7HCyls84g==", - "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/babel__traverse": "^7.0.6", - "@types/prettier": "^2.1.5", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.5.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.5.0", - "semver": "^7.3.5" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-snapshot/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-snapshot/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-snapshot/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-snapshot/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-snapshot/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jest-snapshot/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-transform-stub": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/jest-transform-stub/-/jest-transform-stub-2.0.0.tgz", - "integrity": "sha512-lspHaCRx/mBbnm3h4uMMS3R5aZzMwyNpNIJLXj4cEsV0mIUtS4IjYJLSoyjRCtnxb6RIGJ4NL2quZzfIeNhbkg==", - "dev": true - }, - "node_modules/jest-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", - "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", - "dev": true, - "dependencies": { - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-util/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-util/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-util/node_modules/ci-info": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.1.tgz", - "integrity": "sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-util/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-util/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-util/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-util/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-validate": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.5.0.tgz", - "integrity": "sha512-pC26etNIi+y3HV8A+tUGr/lph9B18GnzSRAkPaaZJIE1eFdiYm6/CewuiJQ8/RlfHd1u/8Ioi8/sJ+CmbA+zAQ==", - "dev": true, - "dependencies": { - "@jest/types": "^29.5.0", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", - "leven": "^3.1.0", - "pretty-format": "^29.5.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-validate/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-validate/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-validate/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-validate/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-validate/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-validate/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-watcher": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.5.0.tgz", - "integrity": "sha512-KmTojKcapuqYrKDpRwfqcQ3zjMlwu27SYext9pt4GlF5FUgB+7XE1mcCnSm6a4uUpFyQIkb6ZhzZvHl+jiBCiA==", - "dev": true, - "dependencies": { - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.5.0", - "string-length": "^4.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-watcher/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-watcher/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-watcher/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-watcher/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-watcher/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-watcher/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/jest-worker/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/joi": { - "version": "17.6.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.6.0.tgz", - "integrity": "sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw==", - "dev": true, - "dependencies": { - "@hapi/hoek": "^9.0.0", - "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.3", - "@sideway/formula": "^3.0.0", - "@sideway/pinpoint": "^2.0.0" - } - }, - "node_modules/js-beautify": { - "version": "1.14.6", - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.6.tgz", - "integrity": "sha512-GfofQY5zDp+cuHc+gsEXKPpNw2KbPddreEo35O6jT6i0RVK6LhsoYBhq5TvK4/n74wnA0QbK8gGd+jUZwTMKJw==", - "dev": true, - "dependencies": { - "config-chain": "^1.1.13", - "editorconfig": "^0.15.3", - "glob": "^8.0.3", - "nopt": "^6.0.0" - }, - "bin": { - "css-beautify": "js/bin/css-beautify.js", - "html-beautify": "js/bin/html-beautify.js", - "js-beautify": "js/bin/js-beautify.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/js-beautify/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/js-beautify/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, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/js-beautify/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, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/js-message": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.7.tgz", - "integrity": "sha512-efJLHhLjIyKRewNS9EGZ4UpI8NguuL6fKkhRxVuMmrGV2xN/0APGdQYwLFky5w9naebSZ0OwAGp0G6/2Cg90rA==", - "dev": true, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/js-sdsl": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz", - "integrity": "sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw==", - "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 - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsdom": { - "version": "20.0.3", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", - "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", - "dev": true, - "dependencies": { - "abab": "^2.0.6", - "acorn": "^8.8.1", - "acorn-globals": "^7.0.0", - "cssom": "^0.5.0", - "cssstyle": "^2.3.0", - "data-urls": "^3.0.2", - "decimal.js": "^10.4.2", - "domexception": "^4.0.0", - "escodegen": "^2.0.0", - "form-data": "^4.0.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.1", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.2", - "parse5": "^7.1.1", - "saxes": "^6.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.2", - "w3c-xmlserializer": "^4.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^2.0.0", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^11.0.0", - "ws": "^8.11.0", - "xml-name-validator": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/jsdom/node_modules/entities": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", - "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/jsdom/node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/jsdom/node_modules/tr46": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", - "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", - "dev": true, - "dependencies": { - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/jsdom/node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/jsdom/node_modules/whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", - "dev": true, - "dependencies": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/jsdom/node_modules/ws": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.0.tgz", - "integrity": "sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" - }, - "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==" - }, - "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": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "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==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jszip": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", - "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", - "dependencies": { - "lie": "~3.3.0", - "pako": "~1.0.2", - "readable-stream": "~2.3.6", - "setimmediate": "^1.0.5" - } - }, - "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/klona": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", - "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/launch-editor": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.2.1.tgz", - "integrity": "sha512-On+V7K2uZK6wK7x691ycSUbLD/FyKKelArkbaAMSSJU8JmqmhwN2+mnJDNINuJWSrh2L0kDk+ZQtbC/gOWUwLw==", - "dev": true, - "dependencies": { - "chalk": "^2.3.0", - "shell-quote": "^1.6.1" - } - }, - "node_modules/launch-editor-middleware": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/launch-editor-middleware/-/launch-editor-middleware-2.2.1.tgz", - "integrity": "sha512-s0UO2/gEGiCgei3/2UN3SMuUj1phjQN8lcpnvgLSz26fAzNWPQ6Nf/kF5IFClnfU2ehp6LrmKdMU/beveO+2jg==", - "dev": true, - "dependencies": { - "launch-editor": "^2.2.1" - } - }, - "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", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lie": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", - "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", - "dependencies": { - "immediate": "~3.0.5" - } - }, - "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/lint-staged": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.2.0.tgz", - "integrity": "sha512-GbyK5iWinax5Dfw5obm2g2ccUiZXNGtAS4mCbJ0Lv4rq6iEtfBSjOYdcbOtAIFtM114t0vdpViDDetjVTSd8Vw==", - "dev": true, - "dependencies": { - "chalk": "5.2.0", - "cli-truncate": "^3.1.0", - "commander": "^10.0.0", - "debug": "^4.3.4", - "execa": "^7.0.0", - "lilconfig": "2.1.0", - "listr2": "^5.0.7", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-inspect": "^1.12.3", - "pidtree": "^0.6.0", - "string-argv": "^0.3.1", - "yaml": "^2.2.1" - }, - "bin": { - "lint-staged": "bin/lint-staged.js" - }, - "engines": { - "node": "^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/lint-staged" - } - }, - "node_modules/lint-staged/node_modules/chalk": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", - "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", - "dev": true, - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/lint-staged/node_modules/commander": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.0.tgz", - "integrity": "sha512-zS5PnTI22FIRM6ylNW8G4Ap0IEOyk62fhLSD0+uHRT9McRCLGpkVNvao4bjimpK/GShynyQkFFxHhwMcETmduA==", - "dev": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/lint-staged/node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/lint-staged/node_modules/execa": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz", - "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": "^14.18.0 || ^16.14.0 || >=18.0.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/lint-staged/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/human-signals": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.0.tgz", - "integrity": "sha512-zyzVyMjpGBX2+6cDVZeFPCdtOtdsxOeseRhB9tkQ6xXmGUNrcnBzdEKPy3VPNYz+4gy1oukVOXcrJCunSyc6QQ==", - "dev": true, - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/lint-staged/node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", - "dev": true, - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/lint-staged/node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lint-staged/node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/lint-staged/node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/lint-staged/node_modules/yaml": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz", - "integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==", - "dev": true, - "engines": { - "node": ">= 14" - } - }, - "node_modules/listr2": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-5.0.8.tgz", - "integrity": "sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA==", - "dev": true, - "dependencies": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.19", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.8.0", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": "^14.13.1 || >=16.0.0" - }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" - }, - "peerDependenciesMeta": { - "enquirer": { - "optional": true - } - } - }, - "node_modules/listr2/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/listr2/node_modules/cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, - "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/listr2/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/listr2/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/listr2/node_modules/slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/loader-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", - "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/loader-utils/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "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/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==" - }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true - }, - "node_modules/lodash.defaultsdeep": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz", - "integrity": "sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==", - "dev": true - }, - "node_modules/lodash.kebabcase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", - "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", - "dev": true - }, - "node_modules/lodash.mapvalues": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", - "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=", - "dev": true - }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true - }, - "node_modules/lodash.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/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-update/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-update/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dev": true, - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/lower-case/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", - "dependencies": { - "sourcemap-codec": "^1.4.8" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-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/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", - "dev": true - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memfs": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz", - "integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==", - "dev": true, - "dependencies": { - "fs-monkey": "1.0.3" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "node_modules/merge-source-map": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", - "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", - "dev": true, - "dependencies": { - "source-map": "^0.6.1" - } - }, - "node_modules/merge-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==" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dependencies": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - }, - "bin": { - "miller-rabin": "bin/miller-rabin" - } - }, - "node_modules/miller-rabin/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "dependencies": { - "mime-db": "1.51.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/mini-css-extract-plugin": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.5.3.tgz", - "integrity": "sha512-YseMB8cs8U/KCaAGQoqYmfUuhhGW0a9p9XvWXrxVOkE3/IiISTLw4ALNt7JR5B2eYauFM+PQGSbXMDmVbR7Tfw==", - "dev": true, - "dependencies": { - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/mini-css-extract-plugin/node_modules/ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/mini-css-extract-plugin/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/mini-css-extract-plugin/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/mini-css-extract-plugin/node_modules/schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true - }, - "node_modules/minipass": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz", - "integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mitt": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mitt/-/mitt-2.1.0.tgz", - "integrity": "sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg==" - }, - "node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/module-alias": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/module-alias/-/module-alias-2.2.2.tgz", - "integrity": "sha512-A/78XjoX2EmNvppVWEhM2oGk3x4lLxnkEA4jTbaK97QKSDjkIoOsKQlfylt/d3kKKi596Qy3NP5XrXJ6fZIC9Q==", - "dev": true - }, - "node_modules/mrmime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz", - "integrity": "sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/multicast-dns": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", - "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", - "dev": true, - "dependencies": { - "dns-packet": "^1.3.1", - "thunky": "^1.0.2" - }, - "bin": { - "multicast-dns": "cli.js" - } - }, - "node_modules/multicast-dns-service-types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", - "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", - "dev": true - }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", - "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "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==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" - }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "node_modules/no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dev": true, - "dependencies": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "node_modules/no-case/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - }, - "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true, - "engines": { - "node": ">= 6.13.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-polyfill-webpack-plugin": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/node-polyfill-webpack-plugin/-/node-polyfill-webpack-plugin-2.0.1.tgz", - "integrity": "sha512-ZUMiCnZkP1LF0Th2caY6J/eKKoA0TefpoVa68m/LQU1I/mE8rGt4fNYGgNuCcK+aG8P8P43nbeJ2RqJMOL/Y1A==", - "dependencies": { - "assert": "^2.0.0", - "browserify-zlib": "^0.2.0", - "buffer": "^6.0.3", - "console-browserify": "^1.2.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.12.0", - "domain-browser": "^4.22.0", - "events": "^3.3.0", - "filter-obj": "^2.0.2", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "^1.0.1", - "process": "^0.11.10", - "punycode": "^2.1.1", - "querystring-es3": "^0.2.1", - "readable-stream": "^4.0.0", - "stream-browserify": "^3.0.0", - "stream-http": "^3.2.0", - "string_decoder": "^1.3.0", - "timers-browserify": "^2.0.12", - "tty-browserify": "^0.0.1", - "type-fest": "^2.14.0", - "url": "^0.11.0", - "util": "^0.12.4", - "vm-browserify": "^1.1.2" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "webpack": ">=5" - } - }, - "node_modules/node-polyfill-webpack-plugin/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/node-polyfill-webpack-plugin/node_modules/readable-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.1.0.tgz", - "integrity": "sha512-sVisi3+P2lJ2t0BPbpK629j8wRW06yKGJUcaLAGXPAUhyUxVJm7VsCTit1PFgT4JHUDMrGNR+ZjSKpzGaRF3zw==", - "dependencies": { - "abort-controller": "^3.0.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/node-polyfill-webpack-plugin/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/node-polyfill-webpack-plugin/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/node-polyfill-webpack-plugin/node_modules/type-fest": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.18.0.tgz", - "integrity": "sha512-pRS+/yrW5TjPPHNOvxhbNZexr2bS63WjrMU8a+VzEBhUi9Tz1pZeD+vQz3ut0svZ46P+SRqMEPnJmk2XnvNzTw==", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/node-releases": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz", - "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==" - }, - "node_modules/nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", - "dev": true, - "dependencies": { - "abbrev": "^1.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "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.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/nth-check": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", - "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/nwsapi": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.2.tgz", - "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==", - "dev": true - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", - "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", - "dev": true, - "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/opener": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", - "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", - "dev": true, - "bin": { - "opener": "bin/opener-bin.js" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ora/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/ora/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/ora/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/ora/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ora/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==" - }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-limit": { - "version": "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/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/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-retry": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.1.tgz", - "integrity": "sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA==", - "dev": true, - "dependencies": { - "@types/retry": "^0.12.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" - }, - "node_modules/param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dev": true, - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/param-case/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "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==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", - "dependencies": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/parse-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": "5.1.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", - "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", - "dev": true - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "dependencies": { - "parse5": "^6.0.1" - } - }, - "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/pascal-case/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - }, - "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==" - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pidtree": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", - "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", - "dev": true, - "bin": { - "pidtree": "bin/pidtree.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/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/portfinder": { - "version": "1.0.28", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", - "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", - "dev": true, - "dependencies": { - "async": "^2.6.2", - "debug": "^3.1.1", - "mkdirp": "^0.5.5" - }, - "engines": { - "node": ">= 0.12.0" - } - }, - "node_modules/portfinder/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/postcss": { - "version": "8.4.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.6.tgz", - "integrity": "sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA==", - "dependencies": { - "nanoid": "^3.2.0", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - } - }, - "node_modules/postcss-calc": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", - "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.9", - "postcss-value-parser": "^4.2.0" - }, - "peerDependencies": { - "postcss": "^8.2.2" - } - }, - "node_modules/postcss-colormin": { - "version": "5.2.5", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.2.5.tgz", - "integrity": "sha512-+X30aDaGYq81mFqwyPpnYInsZQnNpdxMX0ajlY7AExCexEFkPVV+KrO7kXwayqEWL2xwEbNQ4nUO0ZsRWGnevg==", - "dev": true, - "dependencies": { - "browserslist": "^4.16.6", - "caniuse-api": "^3.0.0", - "colord": "^2.9.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-convert-values": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.0.4.tgz", - "integrity": "sha512-bugzSAyjIexdObovsPZu/sBCTHccImJxLyFgeV0MmNBm/Lw5h5XnjfML6gzEmJ3A6nyfCW7hb1JXzcsA4Zfbdw==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-comments": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.0.3.tgz", - "integrity": "sha512-6W5BemziRoqIdAKT+1QjM4bNcJAQ7z7zk073730NHg4cUXh3/rQHHj7pmYxUB9aGhuRhBiUf0pXvIHkRwhQP0Q==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-duplicates": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.3.tgz", - "integrity": "sha512-vPtm1Mf+kp7iAENTG7jI1MN1lk+fBqL5y+qxyi4v3H+lzsXEdfS3dwUZD45KVhgzDEgduur8ycB4hMegyMTeRw==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-empty": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.0.3.tgz", - "integrity": "sha512-xGJugpaXKakwKI7sSdZjUuN4V3zSzb2Y0LOlmTajFbNinEjTfVs9PFW2lmKBaC/E64WwYppfqLD03P8l9BuueA==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-overridden": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.0.4.tgz", - "integrity": "sha512-3j9QH0Qh1KkdxwiZOW82cId7zdwXVQv/gRXYDnwx5pBtR1sTkU4cXRK9lp5dSdiM0r0OICO/L8J6sV1/7m0kHg==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-loader": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", - "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", - "dev": true, - "dependencies": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.5", - "semver": "^7.3.5" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "postcss": "^7.0.0 || ^8.0.1", - "webpack": "^5.0.0" - } - }, - "node_modules/postcss-loader/node_modules/cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", - "dev": true, - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/postcss-loader/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/postcss-merge-longhand": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.0.6.tgz", - "integrity": "sha512-rkmoPwQO6ymJSmWsX6l2hHeEBQa7C4kJb9jyi5fZB1sE8nSCv7sqchoYPixRwX/yvLoZP2y6FA5kcjiByeJqDg==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0", - "stylehacks": "^5.0.3" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-merge-rules": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.0.6.tgz", - "integrity": "sha512-nzJWJ9yXWp8AOEpn/HFAW72WKVGD2bsLiAmgw4hDchSij27bt6TF+sIK0cJUBAYT3SGcjtGGsOR89bwkkMuMgQ==", - "dev": true, - "dependencies": { - "browserslist": "^4.16.6", - "caniuse-api": "^3.0.0", - "cssnano-utils": "^3.0.2", - "postcss-selector-parser": "^6.0.5" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-font-values": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.0.4.tgz", - "integrity": "sha512-RN6q3tyuEesvyCYYFCRGJ41J1XFvgV+dvYGHr0CeHv8F00yILlN8Slf4t8XW4IghlfZYCeyRrANO6HpJ948ieA==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-gradients": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.0.6.tgz", - "integrity": "sha512-E/dT6oVxB9nLGUTiY/rG5dX9taugv9cbLNTFad3dKxOO+BQg25Q/xo2z2ddG+ZB1CbkZYaVwx5blY8VC7R/43A==", - "dev": true, - "dependencies": { - "colord": "^2.9.1", - "cssnano-utils": "^3.0.2", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-params": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.0.5.tgz", - "integrity": "sha512-YBNuq3Rz5LfLFNHb9wrvm6t859b8qIqfXsWeK7wROm3jSKNpO1Y5e8cOyBv6Acji15TgSrAwb3JkVNCqNyLvBg==", - "dev": true, - "dependencies": { - "browserslist": "^4.16.6", - "cssnano-utils": "^3.0.2", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-selectors": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.1.3.tgz", - "integrity": "sha512-9RJfTiQEKA/kZhMaEXND893nBqmYQ8qYa/G+uPdVnXF6D/FzpfI6kwBtWEcHx5FqDbA79O9n6fQJfrIj6M8jvQ==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.5" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", - "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-normalize-charset": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.0.3.tgz", - "integrity": "sha512-iKEplDBco9EfH7sx4ut7R2r/dwTnUqyfACf62Unc9UiyFuI7uUqZZtY+u+qp7g8Qszl/U28HIfcsI3pEABWFfA==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-display-values": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.3.tgz", - "integrity": "sha512-FIV5FY/qs4Ja32jiDb5mVj5iWBlS3N8tFcw2yg98+8MkRgyhtnBgSC0lxU+16AMHbjX5fbSJgw5AXLMolonuRQ==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-positions": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.0.4.tgz", - "integrity": "sha512-qynirjBX0Lc73ROomZE3lzzmXXTu48/QiEzKgMeqh28+MfuHLsuqC9po4kj84igZqqFGovz8F8hf44hA3dPYmQ==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-repeat-style": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.4.tgz", - "integrity": "sha512-Innt+wctD7YpfeDR7r5Ik6krdyppyAg2HBRpX88fo5AYzC1Ut/l3xaxACG0KsbX49cO2n5EB13clPwuYVt8cMA==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-string": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.0.4.tgz", - "integrity": "sha512-Dfk42l0+A1CDnVpgE606ENvdmksttLynEqTQf5FL3XGQOyqxjbo25+pglCUvziicTxjtI2NLUR6KkxyUWEVubQ==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-timing-functions": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.3.tgz", - "integrity": "sha512-QRfjvFh11moN4PYnJ7hia4uJXeFotyK3t2jjg8lM9mswleGsNw2Lm3I5wO+l4k1FzK96EFwEVn8X8Ojrp2gP4g==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-unicode": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.4.tgz", - "integrity": "sha512-W79Regn+a+eXTzB+oV/8XJ33s3pDyFTND2yDuUCo0Xa3QSy1HtNIfRVPXNubHxjhlqmMFADr3FSCHT84ITW3ig==", - "dev": true, - "dependencies": { - "browserslist": "^4.16.6", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-url": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.0.5.tgz", - "integrity": "sha512-Ws3tX+PcekYlXh+ycAt0wyzqGthkvVtZ9SZLutMVvHARxcpu4o7vvXcNoiNKyjKuWecnjS6HDI3fjBuDr5MQxQ==", - "dev": true, - "dependencies": { - "normalize-url": "^6.0.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-whitespace": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.4.tgz", - "integrity": "sha512-wsnuHolYZjMwWZJoTC9jeI2AcjA67v4UuidDrPN9RnX8KIZfE+r2Nd6XZRwHVwUiHmRvKQtxiqo64K+h8/imaw==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-ordered-values": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.0.5.tgz", - "integrity": "sha512-mfY7lXpq+8bDEHfP+muqibDPhZ5eP9zgBEF9XRvoQgXcQe2Db3G1wcvjbnfjXG6wYsl+0UIjikqq4ym1V2jGMQ==", - "dev": true, - "dependencies": { - "cssnano-utils": "^3.0.2", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-reduce-initial": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.0.3.tgz", - "integrity": "sha512-c88TkSnQ/Dnwgb4OZbKPOBbCaauwEjbECP5uAuFPOzQ+XdjNjRH7SG0dteXrpp1LlIFEKK76iUGgmw2V0xeieA==", - "dev": true, - "dependencies": { - "browserslist": "^4.16.6", - "caniuse-api": "^3.0.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-reduce-transforms": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.4.tgz", - "integrity": "sha512-VIJB9SFSaL8B/B7AXb7KHL6/GNNbbCHslgdzS9UDfBZYIA2nx8NLY7iD/BXFSO/1sRUILzBTfHCoW5inP37C5g==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.0.9", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz", - "integrity": "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-svgo": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.0.4.tgz", - "integrity": "sha512-yDKHvULbnZtIrRqhZoA+rxreWpee28JSRH/gy9727u0UCgtpv1M/9WEWY3xySlFa0zQJcqf6oCBJPR5NwkmYpg==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0", - "svgo": "^2.7.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-unique-selectors": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.0.4.tgz", - "integrity": "sha512-5ampwoSDJCxDPoANBIlMgoBcYUHnhaiuLYJR5pj1DLnYQvMRVyFuTA5C3Bvt+aHtiqWpJkD/lXT50Vo1D0ZsAQ==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.5" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.6.tgz", - "integrity": "sha512-mtuzdiBbHwPEgl7NxWlqOkithPyp4VN93V7VeHVWBF+ad3I5avc0RVDT4oImXQy9H/AqxA2NSQH8pSxHW6FYbQ==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/pretty-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", - "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", - "dev": true, - "dependencies": { - "lodash": "^4.17.20", - "renderkid": "^3.0.0" - } - }, - "node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.4.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/progress-webpack-plugin": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/progress-webpack-plugin/-/progress-webpack-plugin-1.0.12.tgz", - "integrity": "sha512-b0dMK6D7pFicDzSdh+sU0p/gp3n5QAGwjPbgacmYB/eVQpayzf9lKTQLYMnTAbk69fKoXSoVNl/+IkobJblL1A==", - "dev": true, - "dependencies": { - "chalk": "^2.1.0", - "figures": "^2.0.0", - "log-update": "^2.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "peerDependencies": { - "webpack": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0" - } - }, - "node_modules/progress-webpack-plugin/node_modules/ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/progress-webpack-plugin/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/progress-webpack-plugin/node_modules/cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "dependencies": { - "restore-cursor": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/progress-webpack-plugin/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/progress-webpack-plugin/node_modules/log-update": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", - "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", - "dev": true, - "dependencies": { - "ansi-escapes": "^3.0.0", - "cli-cursor": "^2.0.0", - "wrap-ansi": "^3.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/progress-webpack-plugin/node_modules/mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/progress-webpack-plugin/node_modules/onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "dependencies": { - "mimic-fn": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/progress-webpack-plugin/node_modules/restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "dependencies": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/progress-webpack-plugin/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/progress-webpack-plugin/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/progress-webpack-plugin/node_modules/wrap-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", - "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", - "dev": true, - "dependencies": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "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/proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", - "dev": true - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxy-addr/node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "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/public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dependencies": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/public-encrypt/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "engines": { - "node": ">=6" - } - }, - "node_modules/pure-rand": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.0.tgz", - "integrity": "sha512-rLSBxJjP+4DQOgcJAx6RZHT2he2pkhQdSnofG5VWyVl6GRq/K02ISOuOLcsMOrtKDIJb8JN2zm3FFzWNbezdPw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ] - }, - "node_modules/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", - "dev": true, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", - "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==", - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dependencies": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", - "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "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/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.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz", - "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==", - "dev": true, - "dependencies": { - "regenerate": "^1.4.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", - "dev": true - }, - "node_modules/regenerator-transform": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz", - "integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.8.4" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/regexpu-core": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.1.0.tgz", - "integrity": "sha512-bb6hk+xWd2PEOkj5It46A16zFMs2mv86Iwpdu94la4S3sJ7C973h2dHpYKwIBGaWSO7cIRJ+UX0IeMaWcO4qwA==", - "dev": true, - "dependencies": { - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.0.1", - "regjsgen": "^0.6.0", - "regjsparser": "^0.8.2", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regjsgen": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz", - "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==", - "dev": true - }, - "node_modules/regjsparser": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz", - "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==", - "dev": true, - "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - } - }, - "node_modules/relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/renderkid": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", - "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", - "dev": true, - "dependencies": { - "css-select": "^4.1.3", - "dom-converter": "^0.2.0", - "htmlparser2": "^6.1.0", - "lodash": "^4.17.21", - "strip-ansi": "^6.0.1" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, - "node_modules/resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.8.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-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", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve.exports": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.1.tgz", - "integrity": "sha512-OEJWVeimw8mgQuj3HfkNl4KqRevH7lzeQNaWRPfx0PPse7Jk6ozcsG4FKVgtzDsC1KUF+YlTHh17NcgHOPykLw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rxjs": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", - "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", - "dev": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/rxjs/node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", - "dev": true - }, - "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/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/saxes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", - "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "dev": true, - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=v12.22.7" - } - }, - "node_modules/schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", - "dev": true - }, - "node_modules/selfsigned": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.0.tgz", - "integrity": "sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ==", - "dev": true, - "dependencies": { - "node-forge": "^1.2.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", - "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "1.8.1", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", - "dev": true, - "dependencies": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-index/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "node_modules/serve-index/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "node_modules/serve-static": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", - "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", - "dev": true, - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/shell-quote": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", - "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", - "dev": true - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha512-fCvEXfh6NWpm+YSuY2bpXb/VIihqWA6hLsgboC+0nl71Q7N7o2eaCW8mJa/NLvQhs6jpd3VZV4UiUQlV6+lc8g==", - "dev": true - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/sirv": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.19.tgz", - "integrity": "sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ==", - "dev": true, - "dependencies": { - "@polka/url": "^1.0.0-next.20", - "mrmime": "^1.0.0", - "totalist": "^1.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "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": "5.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.0.0.tgz", - "integrity": "sha512-n6KkmvKS0623igEVj3FF0OZs1gYYJ0o0Hj939yc1fyxl2xt+xYpLnzJB6xBSqOfV9ZFLEWodBBN/heZJahuIJQ==", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.1.0.tgz", - "integrity": "sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", - "dev": true, - "dependencies": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" - } - }, - "node_modules/sortablejs": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz", - "integrity": "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w==", - "peer": 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==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "engines": { - "node": ">=0.10.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==", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "deprecated": "Please use @jridgewell/sourcemap-codec instead" - }, - "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", - "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", - "dev": true - }, - "node_modules/spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dev": true, - "dependencies": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, - "dependencies": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - } - }, - "node_modules/spdy-transport/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/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/stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "dev": true - }, - "node_modules/stack-utils": { - "version": "2.0.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/stackframe": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.0.tgz", - "integrity": "sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA==", - "dev": true - }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/stream-browserify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", - "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", - "dependencies": { - "inherits": "~2.0.4", - "readable-stream": "^3.5.0" - } - }, - "node_modules/stream-browserify/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/stream-http": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", - "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", - "dependencies": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "xtend": "^4.0.2" - } - }, - "node_modules/stream-http/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string-argv": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", - "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", - "dev": true, - "engines": { - "node": ">=0.6.19" - } - }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", - "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", - "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-indent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", - "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/stylehacks": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.0.3.tgz", - "integrity": "sha512-ENcUdpf4yO0E1rubu8rkxI+JGQk4CgjchynZ4bDBJDfqdy+uhTRSWb8/F3Jtu+Bw5MW45Po3/aQGeIyyxgQtxg==", - "dev": true, - "dependencies": { - "browserslist": "^4.16.6", - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/svg-tags": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", - "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", - "dev": true - }, - "node_modules/svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", - "dev": true, - "dependencies": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" - }, - "bin": { - "svgo": "bin/svgo" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/svgo/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/symbol-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/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/terser": { - "version": "5.17.3", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.17.3.tgz", - "integrity": "sha512-AudpAZKmZHkG9jueayypz4duuCFJMMNGRMwaPvQKWfxKedh8Z2x3OCoDqIIi1xx5+iwx1u6Au8XQcc9Lke65Yg==", - "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.8", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.8.tgz", - "integrity": "sha512-WiHL3ElchZMsK27P8uIUh4604IgJyAW47LVXGbEoB21DbQcZ+OuMpGjVYnEUaqcWM6dO8uS2qUbA7LSCWqvsbg==", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.8" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", - "dev": true, - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/thread-loader": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/thread-loader/-/thread-loader-3.0.4.tgz", - "integrity": "sha512-ByaL2TPb+m6yArpqQUZvP+5S1mZtXsEP7nWKKlAUTm7fCml8kB5s1uI3+eHRP2bk5mVYfRSBI7FFf+tWEyLZwA==", - "dev": true, - "dependencies": { - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^4.1.0", - "loader-utils": "^2.0.0", - "neo-async": "^2.6.2", - "schema-utils": "^3.0.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.27.0 || ^5.0.0" - } - }, - "node_modules/thread-loader/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/thread-loader/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "node_modules/thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true - }, - "node_modules/timers-browserify": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", - "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", - "dependencies": { - "setimmediate": "^1.0.4" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/timsort": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", - "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", - "dev": true - }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/totalist": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz", - "integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/tough-cookie": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz", - "integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==", - "dev": true, - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tough-cookie/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": ">= 4.0.0" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "dev": true - }, - "node_modules/ts-jest": { - "version": "29.0.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.5.tgz", - "integrity": "sha512-PL3UciSgIpQ7f6XjVOmbi96vmDHUqAyqDr8YxzopDqX3kfgYtX1cuNeBjP+L9sFXi6nzsGGA6R3fP3DDDJyrxA==", - "dev": true, - "dependencies": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^29.0.0", - "json5": "^2.2.3", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "7.x", - "yargs-parser": "^21.0.1" - }, - "bin": { - "ts-jest": "cli.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": ">=7.0.0-beta.0 <8", - "@jest/types": "^29.0.0", - "babel-jest": "^29.0.0", - "jest": "^29.0.0", - "typescript": ">=4.3" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "@jest/types": { - "optional": true - }, - "babel-jest": { - "optional": true - }, - "esbuild": { - "optional": true - } - } - }, - "node_modules/ts-jest/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ts-jest/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/ts-loader": { - "version": "9.2.6", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.2.6.tgz", - "integrity": "sha512-QMTC4UFzHmu9wU2VHZEmWWE9cUajjfcdcws+Gh7FhiO+Dy0RnR1bNz0YCHqhI0yRowCE9arVnNxYHqELOy9Hjw==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.0.0", - "micromatch": "^4.0.0", - "semver": "^7.3.4" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "typescript": "*", - "webpack": "^5.0.0" - } - }, - "node_modules/ts-loader/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ts-loader/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/ts-loader/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/ts-loader/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/ts-loader/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ts-loader/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ts-loader/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tsconfig": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", - "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", - "dev": true, - "dependencies": { - "@types/strip-bom": "^3.0.0", - "@types/strip-json-comments": "0.0.30", - "strip-bom": "^3.0.0", - "strip-json-comments": "^2.0.0" - } - }, - "node_modules/tsconfig/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/tsconfig/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tty-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", - "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "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/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typescript": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz", - "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=12.20" - } - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", - "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", - "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.4.tgz", - "integrity": "sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "browserslist-lint": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==", - "dependencies": { - "punycode": "1.3.2", - "querystring": "0.2.0" - } - }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "node_modules/url/node_modules/punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" - }, - "node_modules/util": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", - "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", - "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "safe-buffer": "^5.1.2", - "which-typed-array": "^1.1.2" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "node_modules/utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", - "dev": true - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/v8-to-istanbul": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", - "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/vm-browserify": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", - "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" - }, - "node_modules/vue": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.47.tgz", - "integrity": "sha512-60188y/9Dc9WVrAZeUVSDxRQOZ+z+y5nO2ts9jWXSTkMvayiWxCWOWtBQoYjLeccfXkiiPZWAHcV+WTPhkqJHQ==", - "dependencies": { - "@vue/compiler-dom": "3.2.47", - "@vue/compiler-sfc": "3.2.47", - "@vue/runtime-dom": "3.2.47", - "@vue/server-renderer": "3.2.47", - "@vue/shared": "3.2.47" - } - }, - "node_modules/vue-chart-3": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/vue-chart-3/-/vue-chart-3-3.1.8.tgz", - "integrity": "sha512-zX5ajjQi/PocEqLETlej3vp92q/tnI/Fvu2RVb++Kap8qOrXu6PXCpodi73BFrWzEGZIAnqoUxC3OIkRWD657g==", - "dependencies": { - "@vue/runtime-core": "latest", - "@vue/runtime-dom": "latest", - "csstype": "latest", - "lodash-es": "latest" - }, - "peerDependencies": { - "chart.js": "=> ^3.1.0", - "vue": ">= 3" - } - }, - "node_modules/vue-chart-3/node_modules/csstype": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz", - "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==" - }, - "node_modules/vue-draggable-next": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/vue-draggable-next/-/vue-draggable-next-2.1.1.tgz", - "integrity": "sha512-f5lmA7t6LMaL4viR7dU30zzvqJzaKQs0ymL0Jy9UDT9uiZ2tXF3MzPzEvpTH2UODXZJkT+SnjeV1fXHMsgXLYA==", - "peerDependencies": { - "sortablejs": "^1.14.0", - "vue": "^3.2.2" - } - }, - "node_modules/vue-eslint-parser": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-8.2.0.tgz", - "integrity": "sha512-hvl8OVT8imlKk/lQyhkshqwQQChzHETcBd5abiO4ePw7ib7QUZLfW+2TUrJHKUvFOCFRJrDin5KJO9OHzB5bRQ==", - "dev": true, - "dependencies": { - "debug": "^4.3.2", - "eslint-scope": "^7.0.0", - "eslint-visitor-keys": "^3.1.0", - "espree": "^9.0.0", - "esquery": "^1.4.0", - "lodash": "^4.17.21", - "semver": "^7.3.5" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=6.0.0" - } - }, - "node_modules/vue-eslint-parser/node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/vue-eslint-parser/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/vue-eslint-parser/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/vue-hot-reload-api": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", - "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==", - "dev": true - }, - "node_modules/vue-loader": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-17.0.0.tgz", - "integrity": "sha512-OWSXjrzIvbF2LtOUmxT3HYgwwubbfFelN8PAP9R9dwpIkj48TVioHhWWSx7W7fk+iF5cgg3CBJRxwTdtLU4Ecg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "hash-sum": "^2.0.0", - "loader-utils": "^2.0.0" - }, - "peerDependencies": { - "webpack": "^4.1.0 || ^5.0.0-0" - } - }, - "node_modules/vue-loader/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/vue-loader/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/vue-loader/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/vue-loader/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/vue-loader/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/vue-loader/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/vue-loader/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/vue-observe-visibility": { - "version": "2.0.0-alpha.1", - "resolved": "https://registry.npmjs.org/vue-observe-visibility/-/vue-observe-visibility-2.0.0-alpha.1.tgz", - "integrity": "sha512-flFbp/gs9pZniXR6fans8smv1kDScJ8RS7rEpMjhVabiKeq7Qz3D9+eGsypncjfIyyU84saU88XZ0zjbD6Gq/g==", - "peerDependencies": { - "vue": "^3.0.0" - } - }, - "node_modules/vue-resize": { - "version": "2.0.0-alpha.1", - "resolved": "https://registry.npmjs.org/vue-resize/-/vue-resize-2.0.0-alpha.1.tgz", - "integrity": "sha512-7+iqOueLU7uc9NrMfrzbG8hwMqchfVfSzpVlCMeJQe4pyibqyoifDNbKTZvwxZKDvGkB+PdFeKvnGZMoEb8esg==", - "peerDependencies": { - "vue": "^3.0.0" - } - }, - "node_modules/vue-router": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.1.6.tgz", - "integrity": "sha512-DYWYwsG6xNPmLq/FmZn8Ip+qrhFEzA14EI12MsMgVxvHFDYvlr4NXpVF5hrRH1wVcDP8fGi5F4rxuJSl8/r+EQ==", - "dependencies": { - "@vue/devtools-api": "^6.4.5" - }, - "funding": { - "url": "https://github.com/sponsors/posva" - }, - "peerDependencies": { - "vue": "^3.2.0" - } - }, - "node_modules/vue-style-loader": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz", - "integrity": "sha512-sFuh0xfbtpRlKfm39ss/ikqs9AbKCoXZBpHeVZ8Tx650o0k0q/YCM7FRvigtxpACezfq6af+a7JeqVTWvncqDg==", - "dev": true, - "dependencies": { - "hash-sum": "^1.0.2", - "loader-utils": "^1.0.2" - } - }, - "node_modules/vue-style-loader/node_modules/hash-sum": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", - "dev": true - }, - "node_modules/vue-template-es2015-compiler": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz", - "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", - "dev": true - }, - "node_modules/vue-virtual-scroller": { - "version": "2.0.0-beta.8", - "resolved": "https://registry.npmjs.org/vue-virtual-scroller/-/vue-virtual-scroller-2.0.0-beta.8.tgz", - "integrity": "sha512-b8/f5NQ5nIEBRTNi6GcPItE4s7kxNHw2AIHLtDp+2QvqdTjVN0FgONwX9cr53jWRgnu+HRLPaWDOR2JPI5MTfQ==", - "dependencies": { - "mitt": "^2.1.0", - "vue-observe-visibility": "^2.0.0-alpha.1", - "vue-resize": "^2.0.0-alpha.1" - }, - "peerDependencies": { - "vue": "^3.2.0" - } - }, - "node_modules/vue3-highlightjs": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/vue3-highlightjs/-/vue3-highlightjs-1.0.5.tgz", - "integrity": "sha512-Q4YNPXu0X5VMBnwPVOk+IQf1Ohp9jFdMitEAmzaz8qVVefcQpN6Dx4BnDGKxja3TLDVF+EgL136wC8YzmoCX9w==", - "dependencies": { - "highlight.js": "^10.3.2" - }, - "peerDependencies": { - "vue": "^3.0.0" - } - }, - "node_modules/vue3-highlightjs/node_modules/highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", - "engines": { - "node": "*" - } - }, - "node_modules/vuex": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/vuex/-/vuex-4.0.2.tgz", - "integrity": "sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==", - "dependencies": { - "@vue/devtools-api": "^6.0.0-beta.11" - }, - "peerDependencies": { - "vue": "^3.0.2" - } - }, - "node_modules/w3c-xmlserializer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", - "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", - "dev": true, - "dependencies": { - "xml-name-validator": "^4.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "dependencies": { - "makeerror": "1.0.12" - } - }, - "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "dependencies": { - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", - "dev": true, - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", - "dev": true - }, - "node_modules/webpack": { - "version": "5.82.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.82.1.tgz", - "integrity": "sha512-C6uiGQJ+Gt4RyHXXYt+v9f+SN1v83x68URwgxNQ98cvH8kxiuywWGP4XeNZ1paOzZ63aY3cTciCEQJNFUljlLw==", - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.14.0", - "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.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.2", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-bundle-analyzer": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz", - "integrity": "sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ==", - "dev": true, - "dependencies": { - "acorn": "^8.0.4", - "acorn-walk": "^8.0.0", - "chalk": "^4.1.0", - "commander": "^7.2.0", - "gzip-size": "^6.0.0", - "lodash": "^4.17.20", - "opener": "^1.5.2", - "sirv": "^1.0.7", - "ws": "^7.3.1" - }, - "bin": { - "webpack-bundle-analyzer": "lib/bin/analyzer.js" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/webpack-bundle-analyzer/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/webpack-chain": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-6.5.1.tgz", - "integrity": "sha512-7doO/SRtLu8q5WM0s7vPKPWX580qhi0/yBHkOxNkv50f6qB76Zy9o2wRTrrPULqYTvQlVHuvbA8v+G5ayuUDsA==", - "dev": true, - "dependencies": { - "deepmerge": "^1.5.2", - "javascript-stringify": "^2.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/webpack-chain/node_modules/deepmerge": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz", - "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-dev-middleware": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz", - "integrity": "sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg==", - "dev": true, - "dependencies": { - "colorette": "^2.0.10", - "memfs": "^3.4.1", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/webpack-dev-middleware/node_modules/ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/webpack-dev-middleware/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/webpack-dev-middleware/node_modules/schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/webpack-dev-server": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.7.4.tgz", - "integrity": "sha512-nfdsb02Zi2qzkNmgtZjkrMOcXnYZ6FLKcQwpxT7MvmHKc+oTtDsBju8j+NMyAygZ9GW1jMEUpy3itHtqgEhe1A==", - "dev": true, - "dependencies": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.2.2", - "ansi-html-community": "^0.0.8", - "bonjour": "^3.5.0", - "chokidar": "^3.5.3", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^1.6.0", - "default-gateway": "^6.0.3", - "del": "^6.0.0", - "express": "^4.17.1", - "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", - "http-proxy-middleware": "^2.0.0", - "ipaddr.js": "^2.0.1", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "portfinder": "^1.0.28", - "schema-utils": "^4.0.0", - "selfsigned": "^2.0.0", - "serve-index": "^1.9.1", - "sockjs": "^0.3.21", - "spdy": "^4.0.2", - "strip-ansi": "^7.0.0", - "webpack-dev-middleware": "^5.3.1", - "ws": "^8.4.2" - }, - "bin": { - "webpack-dev-server": "bin/webpack-dev-server.js" - }, - "engines": { - "node": ">= 12.13.0" - }, - "peerDependencies": { - "webpack": "^4.37.0 || ^5.0.0" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-dev-server/node_modules/ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack-dev-server/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/webpack-dev-server/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/webpack-dev-server/node_modules/schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/webpack-dev-server/node_modules/strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/webpack-merge": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", - "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", - "dev": true, - "dependencies": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack-virtual-modules": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.4.3.tgz", - "integrity": "sha512-5NUqC2JquIL2pBAAo/VfBP6KuGkHIZQXW/lNKupLPfhViwh8wNsu0BObtl09yuKZszeEUfbXz8xhrHvSG16Nqw==", - "dev": true - }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", - "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/webpack/node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dev": true, - "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/whatwg-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", - "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", - "dev": true, - "dependencies": { - "iconv-lite": "0.6.3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/whatwg-fetch": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", - "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==", - "dev": true - }, - "node_modules/whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz", - "integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==", - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.20.0", - "for-each": "^0.3.3", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/wildcard": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", - "dev": true - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/ws": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", - "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", - "dev": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xml-name-validator": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "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==", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yorkie": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yorkie/-/yorkie-2.0.0.tgz", - "integrity": "sha512-jcKpkthap6x63MB4TxwCyuIGkV0oYP/YRyuQU5UO0Yz/E/ZAu+653/uov+phdmO54n6BcvFRyyt0RRrWdN2mpw==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "execa": "^0.8.0", - "is-ci": "^1.0.10", - "normalize-path": "^1.0.0", - "strip-indent": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/yorkie/node_modules/cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "dependencies": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "node_modules/yorkie/node_modules/execa": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", - "integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=", - "dev": true, - "dependencies": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.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": ">=4" - } - }, - "node_modules/yorkie/node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/yorkie/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/yorkie/node_modules/normalize-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-1.0.0.tgz", - "integrity": "sha1-MtDkcvkf80VwHBWoMRAY07CpA3k=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yorkie/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - } - }, - "dependencies": { - "@achrinza/node-ipc": { - "version": "9.2.5", - "resolved": "https://registry.npmjs.org/@achrinza/node-ipc/-/node-ipc-9.2.5.tgz", - "integrity": "sha512-kBX7Ay911iXZ3VZ1pYltj3Rfu7Ow9H7sK4H4RSfWIfWR2JKNB40K808wppoRIEzE2j2hXLU+r6TJgCAliCGhyQ==", - "dev": true, - "requires": { - "@node-ipc/js-queue": "2.0.3", - "event-pubsub": "4.3.0", - "js-message": "1.0.7" - } - }, - "@ampproject/remapping": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", - "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.0" - } - }, - "@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, - "requires": { - "@babel/highlight": "^7.18.6" - } - }, - "@babel/compat-data": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.6.tgz", - "integrity": "sha512-tzulrgDT0QD6U7BJ4TKVk2SDDg7wlP39P9yAx1RfLy7vP/7rsDRlWVfbWxElslu56+r7QOhB2NSDsabYYruoZQ==", - "dev": true - }, - "@babel/core": { - "version": "7.17.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.5.tgz", - "integrity": "sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.3", - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helpers": "^7.17.2", - "@babel/parser": "^7.17.3", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0" - } - }, - "@babel/generator": { - "version": "7.18.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.7.tgz", - "integrity": "sha512-shck+7VLlY72a2w9c3zYWuE1pwOKEiQHV7GTUbSnhyl5eu3i04t30tBY82ZRWrDfo3gkakCFtevExnxbkf2a3A==", - "dev": true, - "requires": { - "@babel/types": "^7.18.7", - "@jridgewell/gen-mapping": "^0.3.2", - "jsesc": "^2.5.1" - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", - "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.6.tgz", - "integrity": "sha512-KT10c1oWEpmrIRYnthbzHgoOf6B+Xd6a5yhdbNtdhtG7aO1or5HViuf1TQR36xY/QprXA5nvxO6nAjhJ4y38jw==", - "dev": true, - "requires": { - "@babel/helper-explode-assignable-expression": "^7.18.6", - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-compilation-targets": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.6.tgz", - "integrity": "sha512-vFjbfhNCzqdeAtZflUFrG5YIFqGTqsctrtkZ1D/NB0mDW9TwW3GmmUepYY4G9wCET5rY5ugz4OGTcLd614IzQg==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.18.6", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.20.2", - "semver": "^6.3.0" - } - }, - "@babel/helper-create-class-features-plugin": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.6.tgz", - "integrity": "sha512-YfDzdnoxHGV8CzqHGyCbFvXg5QESPFkXlHtvdCkesLjjVMT2Adxe4FGUR5ChIb3DxSaXO12iIOCWoXdsUVwnqw==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.6", - "@babel/helper-function-name": "^7.18.6", - "@babel/helper-member-expression-to-functions": "^7.18.6", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6" - } - }, - "@babel/helper-create-regexp-features-plugin": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.18.6.tgz", - "integrity": "sha512-7LcpH1wnQLGrI+4v+nPp+zUvIkF9x0ddv1Hkdue10tg3gmRnLy97DXh4STiOf1qeIInyD69Qv5kKSZzKD8B/7A==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "regexpu-core": "^5.1.0" - } - }, - "@babel/helper-define-polyfill-provider": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz", - "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==", - "dev": true, - "requires": { - "@babel/helper-compilation-targets": "^7.13.0", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/traverse": "^7.13.0", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - } - }, - "@babel/helper-environment-visitor": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.6.tgz", - "integrity": "sha512-8n6gSfn2baOY+qlp+VSzsosjCVGFqWKmDF0cCWOybh52Dw3SEyoWR1KrhMJASjLwIEkkAufZ0xvr+SxLHSpy2Q==", - "dev": true - }, - "@babel/helper-explode-assignable-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", - "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-function-name": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.6.tgz", - "integrity": "sha512-0mWMxV1aC97dhjCah5U5Ua7668r5ZmSC2DLfH2EZnf9c3/dHZKiFa5pRLMH5tjSl471tY6496ZWk/kjNONBxhw==", - "dev": true, - "requires": { - "@babel/template": "^7.18.6", - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.6.tgz", - "integrity": "sha512-CeHxqwwipekotzPDUuJOfIMtcIHBuc7WAzLmTYWctVigqS5RktNMQ5bEwQSuGewzYnCtTWa3BARXeiLxDTv+Ng==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-module-transforms": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.6.tgz", - "integrity": "sha512-L//phhB4al5uucwzlimruukHB3jRd5JGClwRMD/ROrVjXfLqovYnvQrK/JK36WYyVwGGO7OD3kMyVTjx+WVPhw==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.18.6", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.18.6", - "@babel/template": "^7.18.6", - "@babel/traverse": "^7.18.6", - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", - "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", - "dev": true - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.6.tgz", - "integrity": "sha512-z5wbmV55TveUPZlCLZvxWHtrjuJd+8inFhk7DG0WW87/oJuGDcjDiu7HIvGcpf5464L6xKCg3vNkmlVVz9hwyQ==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.6", - "@babel/helper-wrap-function": "^7.18.6", - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-replace-supers": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.6.tgz", - "integrity": "sha512-fTf7zoXnUGl9gF25fXCWE26t7Tvtyn6H4hkLSYhATwJvw2uYxd3aoXplMSe0g9XbwK7bmxNes7+FGO0rB/xC0g==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.18.6", - "@babel/helper-member-expression-to-functions": "^7.18.6", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/traverse": "^7.18.6", - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-simple-access": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", - "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.6.tgz", - "integrity": "sha512-4KoLhwGS9vGethZpAhYnMejWkX64wsnHPDwvOsKWU6Fg4+AlK2Jz3TyjQLMEPvz+1zemi/WBdkYxCD0bAfIkiw==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", - "dev": true - }, - "@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", - "dev": true - }, - "@babel/helper-wrap-function": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.18.6.tgz", - "integrity": "sha512-I5/LZfozwMNbwr/b1vhhuYD+J/mU+gfGAj5td7l5Rv9WYmH6i3Om69WGKNmlIpsVW/mF6O5bvTKbvDQZVgjqOw==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.18.6", - "@babel/template": "^7.18.6", - "@babel/traverse": "^7.18.6", - "@babel/types": "^7.18.6" - } - }, - "@babel/helpers": { - "version": "7.17.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.2.tgz", - "integrity": "sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ==", - "dev": true, - "requires": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.0", - "@babel/types": "^7.17.0" - } - }, - "@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.7.tgz", - "integrity": "sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==" - }, - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz", - "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.6.tgz", - "integrity": "sha512-Udgu8ZRgrBrttVz6A0EVL0SJ1z+RLbIeqsu632SA1hf0awEppD6TvdznoH+orIF8wtFFAV/Enmw9Y+9oV8TQcw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.6", - "@babel/plugin-proposal-optional-chaining": "^7.18.6" - } - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.6.tgz", - "integrity": "sha512-WAz4R9bvozx4qwf74M+sfqPMKfSqwM0phxPTR6iJIi8robgzXwkEgmeJG1gEKhm6sDqT/U9aV3lfcqybIpev8w==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-remap-async-to-generator": "^7.18.6", - "@babel/plugin-syntax-async-generators": "^7.8.4" - } - }, - "@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-proposal-class-static-block": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz", - "integrity": "sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-class-static-block": "^7.14.5" - } - }, - "@babel/plugin-proposal-decorators": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.18.6.tgz", - "integrity": "sha512-gAdhsjaYmiZVxx5vTMiRfj31nB7LhwBJFMSLzeDxc7X4tKLixup0+k9ughn0RcpBrv9E3PBaXJW7jF5TCihAOg==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/plugin-syntax-decorators": "^7.18.6" - } - }, - "@babel/plugin-proposal-dynamic-import": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", - "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - } - }, - "@babel/plugin-proposal-export-namespace-from": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.6.tgz", - "integrity": "sha512-zr/QcUlUo7GPo6+X1wC98NJADqmy5QTFWWhqeQWiki4XHafJtLl/YMGkmRB2szDD2IYJCCdBTd4ElwhId9T7Xw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - } - }, - "@babel/plugin-proposal-json-strings": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", - "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-json-strings": "^7.8.3" - } - }, - "@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.6.tgz", - "integrity": "sha512-zMo66azZth/0tVd7gmkxOkOjs2rpHyhpcFo565PUP37hSp6hSd9uUKIfTDFMz58BwqgQKhJ9YxtM5XddjXVn+Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - } - }, - "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", - "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - } - }, - "@babel/plugin-proposal-numeric-separator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", - "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - } - }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.6.tgz", - "integrity": "sha512-9yuM6wr4rIsKa1wlUAbZEazkCrgw2sMPEXCr4Rnwetu7cEW1NydkCWytLuYletbf8vFxdJxFhwEZqMpOx2eZyw==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.18.6", - "@babel/helper-compilation-targets": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.18.6" - } - }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", - "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - } - }, - "@babel/plugin-proposal-optional-chaining": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.6.tgz", - "integrity": "sha512-PatI6elL5eMzoypFAiYDpYQyMtXTn+iMhuxxQt5mAXD4fEmKorpSI3PHd+i3JXBJN3xyA6MvJv7at23HffFHwA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.6", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - } - }, - "@babel/plugin-proposal-private-methods": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", - "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-proposal-private-property-in-object": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz", - "integrity": "sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - } - }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", - "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-decorators": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.18.6.tgz", - "integrity": "sha512-fqyLgjcxf/1yhyZ6A+yo1u9gJ7eleFQod2lkaUsF9DQ7sbbY3Ligym3L0+I2c0WmqNKDpoD9UTb1AKP3qRMOAQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-syntax-import-assertions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz", - "integrity": "sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@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, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-jsx": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", - "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-typescript": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz", - "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.19.0" - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz", - "integrity": "sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz", - "integrity": "sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-remap-async-to-generator": "^7.18.6" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", - "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.6.tgz", - "integrity": "sha512-pRqwb91C42vs1ahSAWJkxOxU1RHWDn16XAa6ggQ72wjLlWyYeAcLvTtE0aM8ph3KNydy9CQF2nLYcjq1WysgxQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-classes": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.8.tgz", - "integrity": "sha512-RySDoXdF6hgHSHuAW4aLGyVQdmvEX/iJtjVre52k0pxRq4hzqze+rAVP++NmNv596brBpYmaiKgTZby7ziBnVg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.6", - "@babel/helper-function-name": "^7.18.6", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "globals": "^11.1.0" - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.6.tgz", - "integrity": "sha512-9repI4BhNrR0KenoR9vm3/cIc1tSBIo+u1WVjKCAynahj25O8zfbiE6JtAtHPGQSs4yZ+bA8mRasRP+qc+2R5A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.6.tgz", - "integrity": "sha512-tgy3u6lRp17ilY8r1kP4i2+HDUwxlVqq3RTc943eAWSzGgpU1qhiKpqZ5CMyHReIYPHdo3Kg8v8edKtDqSVEyQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", - "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.6.tgz", - "integrity": "sha512-NJU26U/208+sxYszf82nmGYqVF9QN8py2HFTblPT9hbawi8+1C5a9JubODLTGFuT0qlkqVinmkwOD13s0sZktg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", - "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz", - "integrity": "sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.6.tgz", - "integrity": "sha512-kJha/Gbs5RjzIu0CxZwf5e3aTTSlhZnHMT8zPWnJMjNpLOUgqevg+PN5oMH68nMCXnfiMo4Bhgxqj59KHTlAnA==", - "dev": true, - "requires": { - "@babel/helper-compilation-targets": "^7.18.6", - "@babel/helper-function-name": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.6.tgz", - "integrity": "sha512-x3HEw0cJZVDoENXOp20HlypIHfl0zMIhMVZEBVTfmqbObIpsMxMbmU5nOEO8R7LYT+z5RORKPlTI5Hj4OsO9/Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-member-expression-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", - "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz", - "integrity": "sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz", - "integrity": "sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-simple-access": "^7.18.6", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.6.tgz", - "integrity": "sha512-UbPYpXxLjTw6w6yXX2BYNxF3p6QY225wcTkfQCy3OMnSlS/C3xGtwUjEzGkldb/sy6PWLiCQ3NbYfjWUTI3t4g==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-validator-identifier": "^7.18.6", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-umd": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", - "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.18.6.tgz", - "integrity": "sha512-UmEOGF8XgaIqD74bC8g7iV3RYj8lMf0Bw7NJzvnS9qQhM4mg+1WHKotUIdjxgD2RGrgFLZZPCFPFj3P/kVDYhg==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-new-target": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", - "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", - "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.6" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz", - "integrity": "sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-property-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", - "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz", - "integrity": "sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "regenerator-transform": "^0.15.0" - } - }, - "@babel/plugin-transform-reserved-words": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", - "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-runtime": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.18.6.tgz", - "integrity": "sha512-8uRHk9ZmRSnWqUgyae249EJZ94b0yAGLBIqzZzl+0iEdbno55Pmlt/32JZsHwXD9k/uZj18Aqqk35wBX4CBTXA==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "babel-plugin-polyfill-corejs2": "^0.3.1", - "babel-plugin-polyfill-corejs3": "^0.5.2", - "babel-plugin-polyfill-regenerator": "^0.3.1", - "semver": "^6.3.0" - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", - "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.18.6.tgz", - "integrity": "sha512-ayT53rT/ENF8WWexIRg9AiV9h0aIteyWn5ptfZTZQrjk/+f3WdrJGCY4c9wcgl2+MKkKPhzbYp97FTsquZpDCw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.6" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", - "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.6.tgz", - "integrity": "sha512-UuqlRrQmT2SWRvahW46cGSany0uTlcj8NYOS5sRGYi8FxPYPoLd5DDmMd32ZXEj2Jq+06uGVQKHxa/hJx2EzKw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.6.tgz", - "integrity": "sha512-7m71iS/QhsPk85xSjFPovHPcH3H9qeyzsujhTc+vcdnsXavoWYJ74zx0lP5RhpC5+iDnVLO+PPMHzC11qels1g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-unicode-escapes": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.6.tgz", - "integrity": "sha512-XNRwQUXYMP7VLuy54cr/KS/WeL3AZeORhrmeZ7iewgu+X2eBqmpaLI/hzqr9ZxCeUoq0ASK4GUzSM0BDhZkLFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", - "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/preset-env": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.6.tgz", - "integrity": "sha512-WrthhuIIYKrEFAwttYzgRNQ5hULGmwTj+D6l7Zdfsv5M7IWV/OZbUfbeL++Qrzx1nVJwWROIFhCHRYQV4xbPNw==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.18.6", - "@babel/helper-compilation-targets": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-validator-option": "^7.18.6", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.6", - "@babel/plugin-proposal-async-generator-functions": "^7.18.6", - "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-proposal-class-static-block": "^7.18.6", - "@babel/plugin-proposal-dynamic-import": "^7.18.6", - "@babel/plugin-proposal-export-namespace-from": "^7.18.6", - "@babel/plugin-proposal-json-strings": "^7.18.6", - "@babel/plugin-proposal-logical-assignment-operators": "^7.18.6", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", - "@babel/plugin-proposal-numeric-separator": "^7.18.6", - "@babel/plugin-proposal-object-rest-spread": "^7.18.6", - "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", - "@babel/plugin-proposal-optional-chaining": "^7.18.6", - "@babel/plugin-proposal-private-methods": "^7.18.6", - "@babel/plugin-proposal-private-property-in-object": "^7.18.6", - "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.18.6", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.18.6", - "@babel/plugin-transform-async-to-generator": "^7.18.6", - "@babel/plugin-transform-block-scoped-functions": "^7.18.6", - "@babel/plugin-transform-block-scoping": "^7.18.6", - "@babel/plugin-transform-classes": "^7.18.6", - "@babel/plugin-transform-computed-properties": "^7.18.6", - "@babel/plugin-transform-destructuring": "^7.18.6", - "@babel/plugin-transform-dotall-regex": "^7.18.6", - "@babel/plugin-transform-duplicate-keys": "^7.18.6", - "@babel/plugin-transform-exponentiation-operator": "^7.18.6", - "@babel/plugin-transform-for-of": "^7.18.6", - "@babel/plugin-transform-function-name": "^7.18.6", - "@babel/plugin-transform-literals": "^7.18.6", - "@babel/plugin-transform-member-expression-literals": "^7.18.6", - "@babel/plugin-transform-modules-amd": "^7.18.6", - "@babel/plugin-transform-modules-commonjs": "^7.18.6", - "@babel/plugin-transform-modules-systemjs": "^7.18.6", - "@babel/plugin-transform-modules-umd": "^7.18.6", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.18.6", - "@babel/plugin-transform-new-target": "^7.18.6", - "@babel/plugin-transform-object-super": "^7.18.6", - "@babel/plugin-transform-parameters": "^7.18.6", - "@babel/plugin-transform-property-literals": "^7.18.6", - "@babel/plugin-transform-regenerator": "^7.18.6", - "@babel/plugin-transform-reserved-words": "^7.18.6", - "@babel/plugin-transform-shorthand-properties": "^7.18.6", - "@babel/plugin-transform-spread": "^7.18.6", - "@babel/plugin-transform-sticky-regex": "^7.18.6", - "@babel/plugin-transform-template-literals": "^7.18.6", - "@babel/plugin-transform-typeof-symbol": "^7.18.6", - "@babel/plugin-transform-unicode-escapes": "^7.18.6", - "@babel/plugin-transform-unicode-regex": "^7.18.6", - "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.18.6", - "babel-plugin-polyfill-corejs2": "^0.3.1", - "babel-plugin-polyfill-corejs3": "^0.5.2", - "babel-plugin-polyfill-regenerator": "^0.3.1", - "core-js-compat": "^3.22.1", - "semver": "^6.3.0" - } - }, - "@babel/preset-modules": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", - "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - } - }, - "@babel/runtime": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.6.tgz", - "integrity": "sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, - "@babel/template": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz", - "integrity": "sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.6", - "@babel/types": "^7.18.6" - } - }, - "@babel/traverse": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.6.tgz", - "integrity": "sha512-zS/OKyqmD7lslOtFqbscH6gMLFYOfG1YPqCKfAW5KrTeolKqvB8UelR49Fpr6y93kYkW2Ik00mT1LOGiAGvizw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.6", - "@babel/helper-function-name": "^7.18.6", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.18.6", - "@babel/types": "^7.18.6", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz", - "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", - "to-fast-properties": "^2.0.0" - } - }, - "@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "@eslint-community/eslint-utils": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.3.0.tgz", - "integrity": "sha512-v3oplH6FYCULtFuCeqyuTd9D2WKO937Dxdq+GmHOLL72TTRriLxz2VLlNfkZRsvj6PKnOPAtuT6dwrs/pA5DvA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^3.3.0" - } - }, - "@eslint-community/regexpp": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz", - "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz", - "integrity": "sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - } - } - }, - "@eslint/js": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz", - "integrity": "sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==", - "dev": true - }, - "@hapi/hoek": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz", - "integrity": "sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw==", - "dev": true - }, - "@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", - "dev": true, - "requires": { - "@hapi/hoek": "^9.0.0" - } - }, - "@highlightjs/vue-plugin": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@highlightjs/vue-plugin/-/vue-plugin-2.1.0.tgz", - "integrity": "sha512-E+bmk4ncca+hBEYRV2a+1aIzIV0VSY/e5ArjpuSN9IO7wBJrzUE2u4ESCwrbQD7sAy+jWQjkV5qCCWgc+pu7CQ==", - "requires": {} - }, - "@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - } - }, - "@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 - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "dependencies": { - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "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 - } - } - }, - "@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true - }, - "@jest/console": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.5.0.tgz", - "integrity": "sha512-NEpkObxPwyw/XxZVLPmAGKE89IQRp4puc6IQRPru6JKd1M3fW9v1xM1AnzIJE65hbCkzQAdnL8P47e9hzhiYLQ==", - "dev": true, - "requires": { - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", - "slash": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "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 - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@jest/core": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.5.0.tgz", - "integrity": "sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ==", - "dev": true, - "requires": { - "@jest/console": "^29.5.0", - "@jest/reporters": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.5.0", - "jest-config": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-resolve-dependencies": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "jest-watcher": "^29.5.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", - "dev": true - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "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 - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@jest/environment": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.5.0.tgz", - "integrity": "sha512-5FXw2+wD29YU1d4I2htpRX7jYnAyTRjP2CsXQdo9SAM8g3ifxWPSV0HnClSn71xwctr0U3oZIIH+dtbfmnbXVQ==", - "dev": true, - "requires": { - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "jest-mock": "^29.5.0" - } - }, - "@jest/expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-PueDR2HGihN3ciUNGr4uelropW7rqUfTiOn+8u0leg/42UhblPxHkfoh0Ruu3I9Y1962P3u2DY4+h7GVTSVU6g==", - "dev": true, - "requires": { - "expect": "^29.5.0", - "jest-snapshot": "^29.5.0" - } - }, - "@jest/expect-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", - "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", - "dev": true, - "requires": { - "jest-get-type": "^29.4.3" - } - }, - "@jest/fake-timers": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.5.0.tgz", - "integrity": "sha512-9ARvuAAQcBwDAqOnglWq2zwNIRUDtk/SCkp/ToGEhFv5r86K21l+VEs0qNTaXtyiY0lEePl3kylijSYJQqdbDg==", - "dev": true, - "requires": { - "@jest/types": "^29.5.0", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0" - } - }, - "@jest/globals": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.5.0.tgz", - "integrity": "sha512-S02y0qMWGihdzNbUiqSAiKSpSozSuHX5UYc7QbnHP+D9Lyw8DgGGCinrN9uSuHPeKgSSzvPom2q1nAtBvUsvPQ==", - "dev": true, - "requires": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/types": "^29.5.0", - "jest-mock": "^29.5.0" - } - }, - "@jest/reporters": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.5.0.tgz", - "integrity": "sha512-D05STXqj/M8bP9hQNSICtPqz97u7ffGzZu+9XLucXhkOFBqKcXe04JLZOgIekOxdb73MAoBUFnqvf7MCpKk5OA==", - "dev": true, - "requires": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "jest-worker": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", - "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", - "dev": true, - "requires": { - "@types/node": "*", - "jest-util": "^29.5.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@jest/schemas": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.25.16" - } - }, - "@jest/source-map": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.4.3.tgz", - "integrity": "sha512-qyt/mb6rLyd9j1jUts4EQncvS6Yy3PM9HghnNv86QBlV+zdL2inCdK1tuVlL+J+lpiw2BI67qXOrX3UurBqQ1w==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.15", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - } - }, - "@jest/test-result": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.5.0.tgz", - "integrity": "sha512-fGl4rfitnbfLsrfx1uUpDEESS7zM8JdgZgOCQuxQvL1Sn/I6ijeAVQWGfXI9zb1i9Mzo495cIpVZhA0yr60PkQ==", - "dev": true, - "requires": { - "@jest/console": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - } - }, - "@jest/test-sequencer": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.5.0.tgz", - "integrity": "sha512-yPafQEcKjkSfDXyvtgiV4pevSeyuA6MQr6ZIdVkWJly9vkqjnFfcfhRQqpD5whjoU8EORki752xQmjaqoFjzMQ==", - "dev": true, - "requires": { - "@jest/test-result": "^29.5.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "slash": "^3.0.0" - }, - "dependencies": { - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - } - } - }, - "@jest/transform": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.5.0.tgz", - "integrity": "sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "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 - }, - "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 - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@jest/types": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", - "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", - "dev": true, - "requires": { - "@jest/schemas": "^29.4.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" - }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" - }, - "@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" - }, - "@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "@node-ipc/js-queue": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@node-ipc/js-queue/-/js-queue-2.0.3.tgz", - "integrity": "sha512-fL1wpr8hhD5gT2dA1qifeVaoDFlQR5es8tFuKqjHX+kdOtdNHnxkVZbtIrR2rxnMFvehkjaZRNV2H/gPXlb0hw==", - "dev": true, - "requires": { - "easy-stack": "1.0.1" - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@polka/url": { - "version": "1.0.0-next.21", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", - "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==", - "dev": true - }, - "@sideway/address": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.3.tgz", - "integrity": "sha512-8ncEUtmnTsMmL7z1YPB47kPUq7LpKWJNFPsRzHiIajGC5uXlWGn+AmkYPcHNl8S4tcEGx+cnORnNYaw2wvL+LQ==", - "dev": true, - "requires": { - "@hapi/hoek": "^9.0.0" - } - }, - "@sideway/formula": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", - "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", - "dev": true - }, - "@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", - "dev": true - }, - "@sinclair/typebox": { - "version": "0.25.24", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", - "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", - "dev": true - }, - "@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz", - "integrity": "sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==", - "dev": true, - "requires": { - "@sinonjs/commons": "^2.0.0" - } - }, - "@soda/friendly-errors-webpack-plugin": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.8.1.tgz", - "integrity": "sha512-h2ooWqP8XuFqTXT+NyAFbrArzfQA7R6HTezADrvD9Re8fxMLTPPniLdqVTdDaO0eIoLaAwKT+d6w+5GeTk7Vbg==", - "dev": true, - "requires": { - "chalk": "^3.0.0", - "error-stack-parser": "^2.0.6", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@soda/get-current-script": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@soda/get-current-script/-/get-current-script-1.0.2.tgz", - "integrity": "sha512-T7VNNlYVM1SgQ+VsMYhnDkcGmWhQdL0bDyGm5TlQ3GBXnJscEClUUOKduWTmm2zCnvNLC1hc3JpuXjs/nFOc5w==", - "dev": true - }, - "@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true - }, - "@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "dev": true - }, - "@types/babel__core": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz", - "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==", - "dev": true, - "requires": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dev": true, - "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@types/babel__traverse": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", - "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", - "dev": true, - "requires": { - "@babel/types": "^7.3.0" - } - }, - "@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "dev": true, - "requires": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "@types/bonjour": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", - "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/connect-history-api-fallback": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz", - "integrity": "sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==", - "dev": true, - "requires": { - "@types/express-serve-static-core": "*", - "@types/node": "*" - } - }, - "@types/eslint": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.29.0.tgz", - "integrity": "sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng==", - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/eslint-scope": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", - "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "@types/estree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==" - }, - "@types/express": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", - "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", - "dev": true, - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.28", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", - "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, - "@types/graceful-fs": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", - "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", - "dev": true - }, - "@types/http-proxy": { - "version": "1.17.8", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz", - "integrity": "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "*" - } - }, - "@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, - "requires": { - "@types/istanbul-lib-report": "*" - } - }, - "@types/jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.0.tgz", - "integrity": "sha512-3Emr5VOl/aoBwnWcH/EFQvlSAmjV+XtV9GGu5mwdYew5vhQh0IUZx/60x0TzHDu09Bi7HMx10t/namdJw5QIcg==", - "dev": true, - "requires": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" - } - }, - "@types/jsdom": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", - "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/tough-cookie": "*", - "parse5": "^7.0.0" - }, - "dependencies": { - "entities": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", - "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", - "dev": true - }, - "parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, - "requires": { - "entities": "^4.4.0" - } - } - } - }, - "@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==" - }, - "@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", - "dev": true - }, - "@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true - }, - "@types/node": { - "version": "17.0.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.18.tgz", - "integrity": "sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA==" - }, - "@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true - }, - "@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true - }, - "@types/prettier": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", - "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", - "dev": true - }, - "@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "dev": true - }, - "@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "dev": true - }, - "@types/retry": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", - "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==", - "dev": true - }, - "@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", - "dev": true - }, - "@types/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", - "dev": true, - "requires": { - "@types/express": "*" - } - }, - "@types/serve-static": { - "version": "1.13.10", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", - "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", - "dev": true, - "requires": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "@types/sockjs": { - "version": "0.3.33", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", - "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true - }, - "@types/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==", - "dev": true - }, - "@types/strip-json-comments": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", - "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", - "dev": true - }, - "@types/tough-cookie": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz", - "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==", - "dev": true - }, - "@types/webpack-env": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.16.3.tgz", - "integrity": "sha512-9gtOPPkfyNoEqCQgx4qJKkuNm/x0R2hKR7fdl7zvTJyHnIisuE/LfvXOsYWL0o3qq6uiBnKZNNNzi3l0y/X+xw==", - "dev": true - }, - "@types/ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-ahRJZquUYCdOZf/rCsWg88S0/+cb9wazUBHv6HZEe3XdYaBe2zr/slM8J28X07Hn88Pnm4ezo7N8/ofnOgrPVQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/yargs": { - "version": "17.0.20", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.20.tgz", - "integrity": "sha512-eknWrTHofQuPk2iuqDm1waA7V6xPlbgBoaaXEgYkClhLOnB0TtbW+srJaOToAgawPxPlHQzwypFA2bhZaUGP5A==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, - "@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, - "@typescript-eslint/eslint-plugin": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.56.0.tgz", - "integrity": "sha512-ZNW37Ccl3oMZkzxrYDUX4o7cnuPgU+YrcaYXzsRtLB16I1FR5SHMqga3zGsaSliZADCWo2v8qHWqAYIj8nWCCg==", - "dev": true, - "requires": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.56.0", - "@typescript-eslint/type-utils": "5.56.0", - "@typescript-eslint/utils": "5.56.0", - "debug": "^4.3.4", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.56.0.tgz", - "integrity": "sha512-jGYKyt+iBakD0SA5Ww8vFqGpoV2asSjwt60Gl6YcO8ksQ8s2HlUEyHBMSa38bdLopYqGf7EYQMUIGdT/Luw+sw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.56.0", - "@typescript-eslint/visitor-keys": "5.56.0" - } - }, - "@typescript-eslint/types": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.56.0.tgz", - "integrity": "sha512-JyAzbTJcIyhuUhogmiu+t79AkdnqgPUEsxMTMc/dCZczGMJQh1MK2wgrju++yMN6AWroVAy2jxyPcPr3SWCq5w==", - "dev": true - }, - "@typescript-eslint/visitor-keys": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.56.0.tgz", - "integrity": "sha512-1mFdED7u5bZpX6Xxf5N9U2c18sb+8EvU3tyOIj6LQZ5OOvnmj8BVeNNP603OFPm5KkS1a7IvCIcwrdHXaEMG/Q==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.56.0", - "eslint-visitor-keys": "^3.3.0" - } - }, - "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "@typescript-eslint/parser": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.55.0.tgz", - "integrity": "sha512-ppvmeF7hvdhUUZWSd2EEWfzcFkjJzgNQzVST22nzg958CR+sphy8A6K7LXQZd6V75m1VKjp+J4g/PCEfSCmzhw==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.55.0", - "@typescript-eslint/types": "5.55.0", - "@typescript-eslint/typescript-estree": "5.55.0", - "debug": "^4.3.4" - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.55.0.tgz", - "integrity": "sha512-OK+cIO1ZGhJYNCL//a3ROpsd83psf4dUJ4j7pdNVzd5DmIk+ffkuUIX2vcZQbEW/IR41DYsfJTB19tpCboxQuw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.55.0", - "@typescript-eslint/visitor-keys": "5.55.0" - } - }, - "@typescript-eslint/type-utils": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.56.0.tgz", - "integrity": "sha512-8WxgOgJjWRy6m4xg9KoSHPzBNZeQbGlQOH7l2QEhQID/+YseaFxg5J/DLwWSsi9Axj4e/cCiKx7PVzOq38tY4A==", - "dev": true, - "requires": { - "@typescript-eslint/typescript-estree": "5.56.0", - "@typescript-eslint/utils": "5.56.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - }, - "dependencies": { - "@typescript-eslint/types": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.56.0.tgz", - "integrity": "sha512-JyAzbTJcIyhuUhogmiu+t79AkdnqgPUEsxMTMc/dCZczGMJQh1MK2wgrju++yMN6AWroVAy2jxyPcPr3SWCq5w==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.56.0.tgz", - "integrity": "sha512-41CH/GncsLXOJi0jb74SnC7jVPWeVJ0pxQj8bOjH1h2O26jXN3YHKDT1ejkVz5YeTEQPeLCCRY0U2r68tfNOcg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.56.0", - "@typescript-eslint/visitor-keys": "5.56.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.56.0.tgz", - "integrity": "sha512-1mFdED7u5bZpX6Xxf5N9U2c18sb+8EvU3tyOIj6LQZ5OOvnmj8BVeNNP603OFPm5KkS1a7IvCIcwrdHXaEMG/Q==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.56.0", - "eslint-visitor-keys": "^3.3.0" - } - }, - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "@typescript-eslint/types": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.55.0.tgz", - "integrity": "sha512-M4iRh4AG1ChrOL6Y+mETEKGeDnT7Sparn6fhZ5LtVJF1909D5O4uqK+C5NPbLmpfZ0XIIxCdwzKiijpZUOvOug==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.55.0.tgz", - "integrity": "sha512-I7X4A9ovA8gdpWMpr7b1BN9eEbvlEtWhQvpxp/yogt48fy9Lj3iE3ild/1H3jKBBIYj5YYJmS2+9ystVhC7eaQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.55.0", - "@typescript-eslint/visitor-keys": "5.55.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "dependencies": { - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "@typescript-eslint/utils": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.56.0.tgz", - "integrity": "sha512-XhZDVdLnUJNtbzaJeDSCIYaM+Tgr59gZGbFuELgF7m0IY03PlciidS7UQNKLE0+WpUTn1GlycEr6Ivb/afjbhA==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.56.0", - "@typescript-eslint/types": "5.56.0", - "@typescript-eslint/typescript-estree": "5.56.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.56.0.tgz", - "integrity": "sha512-jGYKyt+iBakD0SA5Ww8vFqGpoV2asSjwt60Gl6YcO8ksQ8s2HlUEyHBMSa38bdLopYqGf7EYQMUIGdT/Luw+sw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.56.0", - "@typescript-eslint/visitor-keys": "5.56.0" - } - }, - "@typescript-eslint/types": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.56.0.tgz", - "integrity": "sha512-JyAzbTJcIyhuUhogmiu+t79AkdnqgPUEsxMTMc/dCZczGMJQh1MK2wgrju++yMN6AWroVAy2jxyPcPr3SWCq5w==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.56.0.tgz", - "integrity": "sha512-41CH/GncsLXOJi0jb74SnC7jVPWeVJ0pxQj8bOjH1h2O26jXN3YHKDT1ejkVz5YeTEQPeLCCRY0U2r68tfNOcg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.56.0", - "@typescript-eslint/visitor-keys": "5.56.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.56.0.tgz", - "integrity": "sha512-1mFdED7u5bZpX6Xxf5N9U2c18sb+8EvU3tyOIj6LQZ5OOvnmj8BVeNNP603OFPm5KkS1a7IvCIcwrdHXaEMG/Q==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.56.0", - "eslint-visitor-keys": "^3.3.0" - } - }, - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.55.0.tgz", - "integrity": "sha512-q2dlHHwWgirKh1D3acnuApXG+VNXpEY5/AwRxDVuEQpxWaB0jCDe0jFMVMALJ3ebSfuOVE8/rMS+9ZOYGg1GWw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.55.0", - "eslint-visitor-keys": "^3.3.0" - } - }, - "@vue/babel-helper-vue-jsx-merge-props": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.2.1.tgz", - "integrity": "sha512-QOi5OW45e2R20VygMSNhyQHvpdUwQZqGPc748JLGCYEy+yp8fNFNdbNIGAgZmi9e+2JHPd6i6idRuqivyicIkA==", - "dev": true - }, - "@vue/babel-helper-vue-transform-on": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.0.2.tgz", - "integrity": "sha512-hz4R8tS5jMn8lDq6iD+yWL6XNB699pGIVLk7WSJnn1dbpjaazsjZQkieJoRX6gW5zpYSCFqQ7jUquPNY65tQYA==", - "dev": true - }, - "@vue/babel-plugin-jsx": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.1.1.tgz", - "integrity": "sha512-j2uVfZjnB5+zkcbc/zsOc0fSNGCMMjaEXP52wdwdIfn0qjFfEYpYZBFKFg+HHnQeJCVrjOeO0YxgaL7DMrym9w==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/plugin-syntax-jsx": "^7.0.0", - "@babel/template": "^7.0.0", - "@babel/traverse": "^7.0.0", - "@babel/types": "^7.0.0", - "@vue/babel-helper-vue-transform-on": "^1.0.2", - "camelcase": "^6.0.0", - "html-tags": "^3.1.0", - "svg-tags": "^1.0.0" - } - }, - "@vue/babel-plugin-transform-vue-jsx": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@vue/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-1.2.1.tgz", - "integrity": "sha512-HJuqwACYehQwh1fNT8f4kyzqlNMpBuUK4rSiSES5D4QsYncv5fxFsLyrxFPG2ksO7t5WP+Vgix6tt6yKClwPzA==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/plugin-syntax-jsx": "^7.2.0", - "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1", - "html-tags": "^2.0.0", - "lodash.kebabcase": "^4.1.1", - "svg-tags": "^1.0.0" - }, - "dependencies": { - "html-tags": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", - "integrity": "sha512-+Il6N8cCo2wB/Vd3gqy/8TZhTD3QvcVeQLCnZiGkGCH3JP28IgGAY41giccp2W4R3jfyJPAP318FQTa1yU7K7g==", - "dev": true - } - } - }, - "@vue/babel-preset-app": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@vue/babel-preset-app/-/babel-preset-app-5.0.8.tgz", - "integrity": "sha512-yl+5qhpjd8e1G4cMXfORkkBlvtPCIgmRf3IYCWYDKIQ7m+PPa5iTm4feiNmCMD6yGqQWMhhK/7M3oWGL9boKwg==", - "dev": true, - "requires": { - "@babel/core": "^7.12.16", - "@babel/helper-compilation-targets": "^7.12.16", - "@babel/helper-module-imports": "^7.12.13", - "@babel/plugin-proposal-class-properties": "^7.12.13", - "@babel/plugin-proposal-decorators": "^7.12.13", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-jsx": "^7.12.13", - "@babel/plugin-transform-runtime": "^7.12.15", - "@babel/preset-env": "^7.12.16", - "@babel/runtime": "^7.12.13", - "@vue/babel-plugin-jsx": "^1.0.3", - "@vue/babel-preset-jsx": "^1.1.2", - "babel-plugin-dynamic-import-node": "^2.3.3", - "core-js": "^3.8.3", - "core-js-compat": "^3.8.3", - "semver": "^7.3.4" - }, - "dependencies": { - "@vue/babel-preset-jsx": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@vue/babel-preset-jsx/-/babel-preset-jsx-1.3.0.tgz", - "integrity": "sha512-WFHjZWoUV/W0VAnEM/vi3zhdKsWrYf1TVFuxrpMQXVjhU8w8cxAUzNkmUDvf5iugCNzQssTJp9LjDPHAcmCqUw==", - "dev": true, - "requires": { - "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1", - "@vue/babel-plugin-transform-vue-jsx": "^1.2.1", - "@vue/babel-sugar-composition-api-inject-h": "^1.3.0", - "@vue/babel-sugar-composition-api-render-instance": "^1.3.0", - "@vue/babel-sugar-functional-vue": "^1.2.2", - "@vue/babel-sugar-inject-h": "^1.2.2", - "@vue/babel-sugar-v-model": "^1.3.0", - "@vue/babel-sugar-v-on": "^1.3.0" - } - }, - "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "@vue/babel-sugar-composition-api-inject-h": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-composition-api-inject-h/-/babel-sugar-composition-api-inject-h-1.3.0.tgz", - "integrity": "sha512-pIDOutEpqbURdVw7xhgxmuDW8Tl+lTgzJZC5jdlUu0lY2+izT9kz3Umd/Tbu0U5cpCJ2Yhu87BZFBzWpS0Xemg==", - "dev": true, - "requires": { - "@babel/plugin-syntax-jsx": "^7.2.0" - } - }, - "@vue/babel-sugar-composition-api-render-instance": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-composition-api-render-instance/-/babel-sugar-composition-api-render-instance-1.3.0.tgz", - "integrity": "sha512-NYNnU2r7wkJLMV5p9Zj4pswmCs037O/N2+/Fs6SyX7aRFzXJRP1/2CZh5cIwQxWQajHXuCUd5mTb7DxoBVWyTg==", - "dev": true, - "requires": { - "@babel/plugin-syntax-jsx": "^7.2.0" - } - }, - "@vue/babel-sugar-functional-vue": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-functional-vue/-/babel-sugar-functional-vue-1.2.2.tgz", - "integrity": "sha512-JvbgGn1bjCLByIAU1VOoepHQ1vFsroSA/QkzdiSs657V79q6OwEWLCQtQnEXD/rLTA8rRit4rMOhFpbjRFm82w==", - "dev": true, - "requires": { - "@babel/plugin-syntax-jsx": "^7.2.0" - } - }, - "@vue/babel-sugar-inject-h": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-inject-h/-/babel-sugar-inject-h-1.2.2.tgz", - "integrity": "sha512-y8vTo00oRkzQTgufeotjCLPAvlhnpSkcHFEp60+LJUwygGcd5Chrpn5480AQp/thrxVm8m2ifAk0LyFel9oCnw==", - "dev": true, - "requires": { - "@babel/plugin-syntax-jsx": "^7.2.0" - } - }, - "@vue/babel-sugar-v-model": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-model/-/babel-sugar-v-model-1.3.0.tgz", - "integrity": "sha512-zcsabmdX48JmxTObn3xmrvvdbEy8oo63DphVyA3WRYGp4SEvJRpu/IvZCVPl/dXLuob2xO/QRuncqPgHvZPzpA==", - "dev": true, - "requires": { - "@babel/plugin-syntax-jsx": "^7.2.0", - "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1", - "@vue/babel-plugin-transform-vue-jsx": "^1.2.1", - "camelcase": "^5.0.0", - "html-tags": "^2.0.0", - "svg-tags": "^1.0.0" - }, - "dependencies": { - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "html-tags": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", - "integrity": "sha512-+Il6N8cCo2wB/Vd3gqy/8TZhTD3QvcVeQLCnZiGkGCH3JP28IgGAY41giccp2W4R3jfyJPAP318FQTa1yU7K7g==", - "dev": true - } - } - }, - "@vue/babel-sugar-v-on": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-on/-/babel-sugar-v-on-1.3.0.tgz", - "integrity": "sha512-8VZgrS0G5bh7+Prj7oJkzg9GvhSPnuW5YT6MNaVAEy4uwxRLJ8GqHenaStfllChTao4XZ3EZkNtHB4Xbr/ePdA==", - "dev": true, - "requires": { - "@babel/plugin-syntax-jsx": "^7.2.0", - "@vue/babel-plugin-transform-vue-jsx": "^1.2.1", - "camelcase": "^5.0.0" - }, - "dependencies": { - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - } - } - }, - "@vue/cli-overlay": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@vue/cli-overlay/-/cli-overlay-5.0.8.tgz", - "integrity": "sha512-KmtievE/B4kcXp6SuM2gzsnSd8WebkQpg3XaB6GmFh1BJGRqa1UiW9up7L/Q67uOdTigHxr5Ar2lZms4RcDjwQ==", - "dev": true - }, - "@vue/cli-plugin-babel": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-babel/-/cli-plugin-babel-5.0.8.tgz", - "integrity": "sha512-a4qqkml3FAJ3auqB2kN2EMPocb/iu0ykeELwed+9B1c1nQ1HKgslKMHMPavYx3Cd/QAx2mBD4hwKBqZXEI/CsQ==", - "dev": true, - "requires": { - "@babel/core": "^7.12.16", - "@vue/babel-preset-app": "^5.0.8", - "@vue/cli-shared-utils": "^5.0.8", - "babel-loader": "^8.2.2", - "thread-loader": "^3.0.0", - "webpack": "^5.54.0" - } - }, - "@vue/cli-plugin-eslint": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-eslint/-/cli-plugin-eslint-5.0.8.tgz", - "integrity": "sha512-d11+I5ONYaAPW1KyZj9GlrV/E6HZePq5L5eAF5GgoVdu6sxr6bDgEoxzhcS1Pk2eh8rn1MxG/FyyR+eCBj/CNg==", - "dev": true, - "requires": { - "@vue/cli-shared-utils": "^5.0.8", - "eslint-webpack-plugin": "^3.1.0", - "globby": "^11.0.2", - "webpack": "^5.54.0", - "yorkie": "^2.0.0" - } - }, - "@vue/cli-plugin-router": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-router/-/cli-plugin-router-5.0.8.tgz", - "integrity": "sha512-Gmv4dsGdAsWPqVijz3Ux2OS2HkMrWi1ENj2cYL75nUeL+Xj5HEstSqdtfZ0b1q9NCce+BFB6QnHfTBXc/fCvMg==", - "dev": true, - "requires": { - "@vue/cli-shared-utils": "^5.0.8" - } - }, - "@vue/cli-plugin-typescript": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-typescript/-/cli-plugin-typescript-5.0.8.tgz", - "integrity": "sha512-JKJOwzJshBqsmp4yLBexwVMebOZ4VGJgbnYvmHVxasJOStF2RxwyW28ZF+zIvASGdat4sAUuo/3mAQyVhm7JHg==", - "dev": true, - "requires": { - "@babel/core": "^7.12.16", - "@types/webpack-env": "^1.15.2", - "@vue/cli-shared-utils": "^5.0.8", - "babel-loader": "^8.2.2", - "fork-ts-checker-webpack-plugin": "^6.4.0", - "globby": "^11.0.2", - "thread-loader": "^3.0.0", - "ts-loader": "^9.2.5", - "webpack": "^5.54.0" - } - }, - "@vue/cli-plugin-vuex": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-vuex/-/cli-plugin-vuex-5.0.8.tgz", - "integrity": "sha512-HSYWPqrunRE5ZZs8kVwiY6oWcn95qf/OQabwLfprhdpFWAGtLStShjsGED2aDpSSeGAskQETrtR/5h7VqgIlBA==", - "dev": true, - "requires": {} - }, - "@vue/cli-service": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@vue/cli-service/-/cli-service-5.0.8.tgz", - "integrity": "sha512-nV7tYQLe7YsTtzFrfOMIHc5N2hp5lHG2rpYr0aNja9rNljdgcPZLyQRb2YRivTHqTv7lI962UXFURcpStHgyFw==", - "dev": true, - "requires": { - "@babel/helper-compilation-targets": "^7.12.16", - "@soda/friendly-errors-webpack-plugin": "^1.8.0", - "@soda/get-current-script": "^1.0.2", - "@types/minimist": "^1.2.0", - "@vue/cli-overlay": "^5.0.8", - "@vue/cli-plugin-router": "^5.0.8", - "@vue/cli-plugin-vuex": "^5.0.8", - "@vue/cli-shared-utils": "^5.0.8", - "@vue/component-compiler-utils": "^3.3.0", - "@vue/vue-loader-v15": "npm:vue-loader@^15.9.7", - "@vue/web-component-wrapper": "^1.3.0", - "acorn": "^8.0.5", - "acorn-walk": "^8.0.2", - "address": "^1.1.2", - "autoprefixer": "^10.2.4", - "browserslist": "^4.16.3", - "case-sensitive-paths-webpack-plugin": "^2.3.0", - "cli-highlight": "^2.1.10", - "clipboardy": "^2.3.0", - "cliui": "^7.0.4", - "copy-webpack-plugin": "^9.0.1", - "css-loader": "^6.5.0", - "css-minimizer-webpack-plugin": "^3.0.2", - "cssnano": "^5.0.0", - "debug": "^4.1.1", - "default-gateway": "^6.0.3", - "dotenv": "^10.0.0", - "dotenv-expand": "^5.1.0", - "fs-extra": "^9.1.0", - "globby": "^11.0.2", - "hash-sum": "^2.0.0", - "html-webpack-plugin": "^5.1.0", - "is-file-esm": "^1.0.0", - "launch-editor-middleware": "^2.2.1", - "lodash.defaultsdeep": "^4.6.1", - "lodash.mapvalues": "^4.6.0", - "mini-css-extract-plugin": "^2.5.3", - "minimist": "^1.2.5", - "module-alias": "^2.2.2", - "portfinder": "^1.0.26", - "postcss": "^8.2.6", - "postcss-loader": "^6.1.1", - "progress-webpack-plugin": "^1.0.12", - "ssri": "^8.0.1", - "terser-webpack-plugin": "^5.1.1", - "thread-loader": "^3.0.0", - "vue-loader": "^17.0.0", - "vue-style-loader": "^4.1.3", - "webpack": "^5.54.0", - "webpack-bundle-analyzer": "^4.4.0", - "webpack-chain": "^6.5.1", - "webpack-dev-server": "^4.7.3", - "webpack-merge": "^5.7.3", - "webpack-virtual-modules": "^0.4.2", - "whatwg-fetch": "^3.6.2" - }, - "dependencies": { - "ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "dev": true, - "requires": { - "minipass": "^3.1.1" - } - } - } - }, - "@vue/cli-shared-utils": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@vue/cli-shared-utils/-/cli-shared-utils-5.0.8.tgz", - "integrity": "sha512-uK2YB7bBVuQhjOJF+O52P9yFMXeJVj7ozqJkwYE9PlMHL1LMHjtCYm4cSdOebuPzyP+/9p0BimM/OqxsevIopQ==", - "dev": true, - "requires": { - "@achrinza/node-ipc": "^9.2.5", - "chalk": "^4.1.2", - "execa": "^1.0.0", - "joi": "^17.4.0", - "launch-editor": "^2.2.1", - "lru-cache": "^6.0.0", - "node-fetch": "^2.6.7", - "open": "^8.0.2", - "ora": "^5.3.0", - "read-pkg": "^5.1.1", - "semver": "^7.3.4", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "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 - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@vue/compiler-core": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.47.tgz", - "integrity": "sha512-p4D7FDnQb7+YJmO2iPEv0SQNeNzcbHdGByJDsT4lynf63AFkOTFN07HsiRSvjGo0QrxR/o3d0hUyNCUnBU2Tig==", - "requires": { - "@babel/parser": "^7.16.4", - "@vue/shared": "3.2.47", - "estree-walker": "^2.0.2", - "source-map": "^0.6.1" - } - }, - "@vue/compiler-dom": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.47.tgz", - "integrity": "sha512-dBBnEHEPoftUiS03a4ggEig74J2YBZ2UIeyfpcRM2tavgMWo4bsEfgCGsu+uJIL/vax9S+JztH8NmQerUo7shQ==", - "requires": { - "@vue/compiler-core": "3.2.47", - "@vue/shared": "3.2.47" - } - }, - "@vue/compiler-sfc": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.47.tgz", - "integrity": "sha512-rog05W+2IFfxjMcFw10tM9+f7i/+FFpZJJ5XHX72NP9eC2uRD+42M3pYcQqDXVYoj74kHMSEdQ/WmCjt8JFksQ==", - "requires": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.47", - "@vue/compiler-dom": "3.2.47", - "@vue/compiler-ssr": "3.2.47", - "@vue/reactivity-transform": "3.2.47", - "@vue/shared": "3.2.47", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7", - "postcss": "^8.1.10", - "source-map": "^0.6.1" - } - }, - "@vue/compiler-ssr": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.47.tgz", - "integrity": "sha512-wVXC+gszhulcMD8wpxMsqSOpvDZ6xKXSVWkf50Guf/S+28hTAXPDYRTbLQ3EDkOP5Xz/+SY37YiwDquKbJOgZw==", - "requires": { - "@vue/compiler-dom": "3.2.47", - "@vue/shared": "3.2.47" - } - }, - "@vue/component-compiler-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.3.0.tgz", - "integrity": "sha512-97sfH2mYNU+2PzGrmK2haqffDpVASuib9/w2/noxiFi31Z54hW+q3izKQXXQZSNhtiUpAI36uSuYepeBe4wpHQ==", - "dev": true, - "requires": { - "consolidate": "^0.15.1", - "hash-sum": "^1.0.2", - "lru-cache": "^4.1.2", - "merge-source-map": "^1.1.0", - "postcss": "^7.0.36", - "postcss-selector-parser": "^6.0.2", - "prettier": "^1.18.2 || ^2.0.0", - "source-map": "~0.6.1", - "vue-template-es2015-compiler": "^1.9.0" - }, - "dependencies": { - "hash-sum": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", - "dev": true - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true - }, - "postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, - "requires": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - } - } - }, - "@vue/devtools-api": { - "version": "6.4.5", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.4.5.tgz", - "integrity": "sha512-JD5fcdIuFxU4fQyXUu3w2KpAJHzTVdN+p4iOX2lMWSHMOoQdMAcpFLZzm9Z/2nmsoZ1a96QEhZ26e50xLBsgOQ==" - }, - "@vue/eslint-config-prettier": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-7.0.0.tgz", - "integrity": "sha512-/CTc6ML3Wta1tCe1gUeO0EYnVXfo3nJXsIhZ8WJr3sov+cGASr6yuiibJTL6lmIBm7GobopToOuB3B6AWyV0Iw==", - "dev": true, - "requires": { - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-prettier": "^4.0.0" - } - }, - "@vue/eslint-config-typescript": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-10.0.0.tgz", - "integrity": "sha512-F94cL8ug3FaYXlCfU5/wiGjk1qeadmoBpRGAOBq+qre3Smdupa59dd6ZJrsfRODpsMPyTG7330juMDsUvpZ3Rw==", - "dev": true, - "requires": { - "@typescript-eslint/eslint-plugin": "^5.0.0", - "@typescript-eslint/parser": "^5.0.0", - "vue-eslint-parser": "^8.0.0" - } - }, - "@vue/reactivity": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.47.tgz", - "integrity": "sha512-7khqQ/75oyyg+N/e+iwV6lpy1f5wq759NdlS1fpAhFXa8VeAIKGgk2E/C4VF59lx5b+Ezs5fpp/5WsRYXQiKxQ==", - "requires": { - "@vue/shared": "3.2.47" - } - }, - "@vue/reactivity-transform": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.47.tgz", - "integrity": "sha512-m8lGXw8rdnPVVIdIFhf0LeQ/ixyHkH5plYuS83yop5n7ggVJU+z5v0zecwEnX7fa7HNLBhh2qngJJkxpwEEmYA==", - "requires": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.47", - "@vue/shared": "3.2.47", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7" - } - }, - "@vue/runtime-core": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.47.tgz", - "integrity": "sha512-RZxbLQIRB/K0ev0K9FXhNbBzT32H9iRtYbaXb0ZIz2usLms/D55dJR2t6cIEUn6vyhS3ALNvNthI+Q95C+NOpA==", - "requires": { - "@vue/reactivity": "3.2.47", - "@vue/shared": "3.2.47" - } - }, - "@vue/runtime-dom": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.47.tgz", - "integrity": "sha512-ArXrFTjS6TsDei4qwNvgrdmHtD930KgSKGhS5M+j8QxXrDJYLqYw4RRcDy1bz1m1wMmb6j+zGLifdVHtkXA7gA==", - "requires": { - "@vue/runtime-core": "3.2.47", - "@vue/shared": "3.2.47", - "csstype": "^2.6.8" - } - }, - "@vue/server-renderer": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.47.tgz", - "integrity": "sha512-dN9gc1i8EvmP9RCzvneONXsKfBRgqFeFZLurmHOveL7oH6HiFXJw5OGu294n1nHc/HMgTy6LulU/tv5/A7f/LA==", - "requires": { - "@vue/compiler-ssr": "3.2.47", - "@vue/shared": "3.2.47" - } - }, - "@vue/shared": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.47.tgz", - "integrity": "sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ==" - }, - "@vue/test-utils": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.3.2.tgz", - "integrity": "sha512-hJnVaYhbrIm0yBS0+e1Y0Sj85cMyAi+PAbK4JHqMRUZ6S622Goa+G7QzkRSyvCteG8wop7tipuEbHoZo26wsSA==", - "dev": true, - "requires": { - "@vue/compiler-dom": "^3.0.1", - "@vue/server-renderer": "^3.0.1", - "js-beautify": "1.14.6" - } - }, - "@vue/vue-loader-v15": { - "version": "npm:vue-loader@15.9.8", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.8.tgz", - "integrity": "sha512-GwSkxPrihfLR69/dSV3+5CdMQ0D+jXg8Ma1S4nQXKJAznYFX14vHdc/NetQc34Dw+rBbIJyP7JOuVb9Fhprvog==", - "dev": true, - "requires": { - "@vue/component-compiler-utils": "^3.1.0", - "hash-sum": "^1.0.2", - "loader-utils": "^1.1.0", - "vue-hot-reload-api": "^2.3.0", - "vue-style-loader": "^4.1.0" - }, - "dependencies": { - "hash-sum": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", - "dev": true - } - } - }, - "@vue/vue3-jest": { - "version": "29.2.3", - "resolved": "https://registry.npmjs.org/@vue/vue3-jest/-/vue3-jest-29.2.3.tgz", - "integrity": "sha512-wbit0rGgy9ARUBtc5dZ6PGCrxazCPs5pZ6ycB0qYMoEPmkRj8lIVUfJmTz03ryIAeVQOcTKnEWdcqgrTErl3vg==", - "dev": true, - "requires": { - "@babel/plugin-transform-modules-commonjs": "^7.2.0", - "chalk": "^2.1.0", - "convert-source-map": "^1.6.0", - "css-tree": "^2.0.1", - "source-map": "0.5.6", - "tsconfig": "^7.0.0" - }, - "dependencies": { - "css-tree": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", - "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dev": true, - "requires": { - "mdn-data": "2.0.30", - "source-map-js": "^1.0.1" - } - }, - "mdn-data": { - "version": "2.0.30", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", - "dev": true - }, - "source-map": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", - "integrity": "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==", - "dev": true - } - } - }, - "@vue/web-component-wrapper": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@vue/web-component-wrapper/-/web-component-wrapper-1.3.0.tgz", - "integrity": "sha512-Iu8Tbg3f+emIIMmI2ycSI8QcEuAUgPTgHwesDU1eKMLE4YC/c/sFbGc70QgMq31ijRftV0R7vCm9co6rldCeOA==", - "dev": true - }, - "@webassemblyjs/ast": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", - "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", - "requires": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" - } - }, - "@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==" - }, - "@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==" - }, - "@webassemblyjs/helper-buffer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", - "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==" - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" - } - }, - "@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==" - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", - "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", - "requires": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" - }, - "@webassemblyjs/wasm-edit": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", - "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", - "requires": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-opt": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6", - "@webassemblyjs/wast-printer": "1.11.6" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", - "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", - "requires": { - "@webassemblyjs/ast": "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" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", - "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", - "requires": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", - "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", - "requires": { - "@webassemblyjs/ast": "1.11.6", - "@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" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", - "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", - "requires": { - "@webassemblyjs/ast": "1.11.6", - "@xtuc/long": "4.2.2" - } - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" - }, - "@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==" - }, - "abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "dev": true - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "requires": { - "event-target-shim": "^5.0.0" - } - }, - "accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - } - }, - "acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==" - }, - "acorn-globals": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", - "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", - "dev": true, - "requires": { - "acorn": "^8.1.0", - "acorn-walk": "^8.0.2" - } - }, - "acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "requires": {} - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true - }, - "address": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz", - "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==", - "dev": true - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "requires": { - "debug": "4" - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "requires": { - "ajv": "^8.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - } - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "requires": {} - }, - "ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "requires": { - "type-fest": "^0.21.3" - } - }, - "ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true - }, - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", - "dev": true - }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "arch": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", - "dev": true - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "array-flatten": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", - "dev": true - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - } - } - }, - "assert": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz", - "integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==", - "requires": { - "es6-object-assign": "^1.1.0", - "is-nan": "^1.2.1", - "object-is": "^1.0.1", - "util": "^0.12.0" - } - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true - }, - "autoprefixer": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.2.tgz", - "integrity": "sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==", - "dev": true, - "requires": { - "browserslist": "^4.19.1", - "caniuse-lite": "^1.0.30001297", - "fraction.js": "^4.1.2", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - } - }, - "available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" - }, - "babel-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.5.0.tgz", - "integrity": "sha512-mA4eCDh5mSo2EcA9xQjVTpmbbNk32Zb3Q3QFQsNhaK56Q+yoXowzFodLux30HRgyOho5rsQ6B0P9QpMkvvnJ0Q==", - "dev": true, - "requires": { - "@jest/transform": "^29.5.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.5.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "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 - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "babel-loader": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz", - "integrity": "sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q==", - "dev": true, - "requires": { - "find-cache-dir": "^3.3.1", - "loader-utils": "^2.0.0", - "make-dir": "^3.1.0", - "schema-utils": "^2.6.5" - }, - "dependencies": { - "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, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - } - } - }, - "babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "dev": true, - "requires": { - "object.assign": "^4.1.0" - } - }, - "babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - } - }, - "babel-plugin-jest-hoist": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz", - "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==", - "dev": true, - "requires": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - } - }, - "babel-plugin-polyfill-corejs2": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz", - "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.13.11", - "@babel/helper-define-polyfill-provider": "^0.3.1", - "semver": "^6.1.1" - } - }, - "babel-plugin-polyfill-corejs3": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz", - "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==", - "dev": true, - "requires": { - "@babel/helper-define-polyfill-provider": "^0.3.1", - "core-js-compat": "^3.21.0" - } - }, - "babel-plugin-polyfill-regenerator": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz", - "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==", - "dev": true, - "requires": { - "@babel/helper-define-polyfill-provider": "^0.3.1" - } - }, - "babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, - "requires": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - } - }, - "babel-preset-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz", - "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==", - "dev": true, - "requires": { - "babel-plugin-jest-hoist": "^29.5.0", - "babel-preset-current-node-syntax": "^1.0.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, - "batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", - "dev": true - }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" - }, - "body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.7", - "raw-body": "2.4.3", - "type-is": "~1.6.18" - }, - "dependencies": { - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "bonjour": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", - "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", - "dev": true, - "requires": { - "array-flatten": "^2.1.0", - "deep-equal": "^1.0.1", - "dns-equal": "^1.0.0", - "dns-txt": "^2.0.2", - "multicast-dns": "^6.0.1", - "multicast-dns-service-types": "^1.1.0" - } - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" - }, - "browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "requires": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "requires": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "requires": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "browserify-rsa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", - "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", - "requires": { - "bn.js": "^5.0.0", - "randombytes": "^2.0.1" - } - }, - "browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", - "requires": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "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==" - } - } - }, - "browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "requires": { - "pako": "~1.0.5" - } - }, - "browserslist": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.1.tgz", - "integrity": "sha512-Nq8MFCSrnJXSc88yliwlzQe3qNe3VntIjhsArW9IJOEPSHNx23FalwApUVbzAWABLhYJJ7y8AynWI/XM8OdfjQ==", - "requires": { - "caniuse-lite": "^1.0.30001359", - "electron-to-chromium": "^1.4.172", - "node-releases": "^2.0.5", - "update-browserslist-db": "^1.0.4" - } - }, - "bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "dev": true, - "requires": { - "fast-json-stable-stringify": "2.x" - } - }, - "bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "requires": { - "node-int64": "^0.4.0" - } - }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "buffer-indexof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", - "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", - "dev": true - }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==" - }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==" - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, - "requires": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - } - } - }, - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "dev": true, - "requires": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, - "caniuse-lite": { - "version": "1.0.30001361", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001361.tgz", - "integrity": "sha512-ybhCrjNtkFji1/Wto6SSJKkWk6kZgVQsDq5QI83SafsF6FXv2JB4df9eEdH6g8sdGgqTXrFLjAxqBGgYoU3azQ==" - }, - "case-sensitive-paths-webpack-plugin": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", - "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true - }, - "chart.js": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.9.1.tgz", - "integrity": "sha512-Ro2JbLmvg83gXF5F4sniaQ+lTbSv18E+TIf2cOeiH1Iqd2PGFOtem+DUufMZsCJwFE7ywPOpfXFBwRTGq7dh6w==" - }, - "chartjs-plugin-datalabels": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/chartjs-plugin-datalabels/-/chartjs-plugin-datalabels-2.2.0.tgz", - "integrity": "sha512-14ZU30lH7n89oq+A4bWaJPnAG8a7ZTk7dKf48YAzMvJjQtjrgg5Dpk9f+LbjCF6bpx3RAGTeL13IXpKQYyRvlw==", - "requires": {} - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==" - }, - "ci-info": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", - "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", - "dev": true - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "cjs-module-lexer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", - "dev": true - }, - "clean-css": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.2.4.tgz", - "integrity": "sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg==", - "dev": true, - "requires": { - "source-map": "~0.6.0" - } - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-highlight": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", - "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "highlight.js": "^10.7.1", - "mz": "^2.4.0", - "parse5": "^5.1.1", - "parse5-htmlparser2-tree-adapter": "^6.0.0", - "yargs": "^16.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "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 - }, - "highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "cli-spinners": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", - "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", - "dev": true - }, - "cli-truncate": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", - "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", - "dev": true, - "requires": { - "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" - }, - "dependencies": { - "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 - }, - "string-width": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.0.tgz", - "integrity": "sha512-7x54QnN21P+XL/v8SuNKvfgsUre6PXpN7mc77N3HlZv+f1SBRGmjxtOud2Z6FZ8DmdkD/IdjCaf9XXbnqmTZGQ==", - "dev": true, - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - } - } - }, - "clipboardy": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz", - "integrity": "sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==", - "dev": true, - "requires": { - "arch": "^2.1.1", - "execa": "^1.0.0", - "is-wsl": "^2.1.1" - } - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true - }, - "collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", - "dev": true - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "colord": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.2.tgz", - "integrity": "sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==", - "dev": true - }, - "colorette": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", - "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, - "requires": { - "mime-db": ">= 1.43.0 < 2" - } - }, - "compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, - "requires": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "config-chain": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", - "dev": true, - "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "connect-history-api-fallback": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", - "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", - "dev": true - }, - "console-browserify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", - "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" - }, - "consolidate": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz", - "integrity": "sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==", - "dev": true, - "requires": { - "bluebird": "^3.1.1" - } - }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==" - }, - "content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "requires": { - "safe-buffer": "5.2.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true - }, - "convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "dev": true - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true - }, - "copy-webpack-plugin": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-9.1.0.tgz", - "integrity": "sha512-rxnR7PaGigJzhqETHGmAcxKnLZSR5u1Y3/bcIv/1FnqXedcL/E2ewK7ZCNrArJKCiSv8yVXhTqetJh8inDvfsA==", - "dev": true, - "requires": { - "fast-glob": "^3.2.7", - "glob-parent": "^6.0.1", - "globby": "^11.0.3", - "normalize-path": "^3.0.0", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0" - }, - "dependencies": { - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - } - } - }, - "core-js": { - "version": "3.29.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.29.1.tgz", - "integrity": "sha512-+jwgnhg6cQxKYIIjGtAHq2nwUOolo9eoFZ4sHfUH09BLXBgxnH4gA0zEd+t+BO2cNB8idaBtZFcFTRjQJRJmAw==" - }, - "core-js-compat": { - "version": "3.23.4", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.23.4.tgz", - "integrity": "sha512-RkSRPe+JYEoflcsuxJWaiMPhnZoFS51FcIxm53k4KzhISCBTmaGlto9dTIrYuk0hnJc3G6pKufAKepHnBq6B6Q==", - "dev": true, - "requires": { - "browserslist": "^4.21.1", - "semver": "7.0.0" - }, - "dependencies": { - "semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", - "dev": true - } - } - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", - "dev": true, - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" - } - }, - "create-ecdh": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", - "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - } - } - }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - } - }, - "css-declaration-sorter": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.1.4.tgz", - "integrity": "sha512-lpfkqS0fctcmZotJGhnxkIyJWvBXgpyi2wsFd4J8VB7wzyrT6Ch/3Q+FMNJpjK4gu1+GN5khOnpU2ZVKrLbhCw==", - "dev": true, - "requires": { - "timsort": "^0.3.0" - } - }, - "css-loader": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.6.0.tgz", - "integrity": "sha512-FK7H2lisOixPT406s5gZM1S3l8GrfhEBT3ZiL2UX1Ng1XWs0y2GPllz/OTyvbaHe12VgQrIXIzuEGVlbUhodqg==", - "dev": true, - "requires": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.5", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.3.5" - }, - "dependencies": { - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "css-minimizer-webpack-plugin": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz", - "integrity": "sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==", - "dev": true, - "requires": { - "cssnano": "^5.0.6", - "jest-worker": "^27.0.2", - "postcss": "^8.3.5", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0", - "source-map": "^0.6.1" - }, - "dependencies": { - "ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - } - } - } - }, - "css-select": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz", - "integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-what": "^5.1.0", - "domhandler": "^4.3.0", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - } - }, - "css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "dev": true, - "requires": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - } - }, - "css-what": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", - "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==", - "dev": true - }, - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true - }, - "cssnano": { - "version": "5.0.17", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.0.17.tgz", - "integrity": "sha512-fmjLP7k8kL18xSspeXTzRhaFtRI7DL9b8IcXR80JgtnWBpvAzHT7sCR/6qdn0tnxIaINUN6OEQu83wF57Gs3Xw==", - "dev": true, - "requires": { - "cssnano-preset-default": "^5.1.12", - "lilconfig": "^2.0.3", - "yaml": "^1.10.2" - } - }, - "cssnano-preset-default": { - "version": "5.1.12", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.1.12.tgz", - "integrity": "sha512-rO/JZYyjW1QNkWBxMGV28DW7d98UDLaF759frhli58QFehZ+D/LSmwQ2z/ylBAe2hUlsIWTq6NYGfQPq65EF9w==", - "dev": true, - "requires": { - "css-declaration-sorter": "^6.0.3", - "cssnano-utils": "^3.0.2", - "postcss-calc": "^8.2.0", - "postcss-colormin": "^5.2.5", - "postcss-convert-values": "^5.0.4", - "postcss-discard-comments": "^5.0.3", - "postcss-discard-duplicates": "^5.0.3", - "postcss-discard-empty": "^5.0.3", - "postcss-discard-overridden": "^5.0.4", - "postcss-merge-longhand": "^5.0.6", - "postcss-merge-rules": "^5.0.6", - "postcss-minify-font-values": "^5.0.4", - "postcss-minify-gradients": "^5.0.6", - "postcss-minify-params": "^5.0.5", - "postcss-minify-selectors": "^5.1.3", - "postcss-normalize-charset": "^5.0.3", - "postcss-normalize-display-values": "^5.0.3", - "postcss-normalize-positions": "^5.0.4", - "postcss-normalize-repeat-style": "^5.0.4", - "postcss-normalize-string": "^5.0.4", - "postcss-normalize-timing-functions": "^5.0.3", - "postcss-normalize-unicode": "^5.0.4", - "postcss-normalize-url": "^5.0.5", - "postcss-normalize-whitespace": "^5.0.4", - "postcss-ordered-values": "^5.0.5", - "postcss-reduce-initial": "^5.0.3", - "postcss-reduce-transforms": "^5.0.4", - "postcss-svgo": "^5.0.4", - "postcss-unique-selectors": "^5.0.4" - } - }, - "cssnano-utils": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.0.2.tgz", - "integrity": "sha512-KhprijuQv2sP4kT92sSQwhlK3SJTbDIsxcfIEySB0O+3m9esFOai7dP9bMx5enHAh2MwarVIcnwiWoOm01RIbQ==", - "dev": true, - "requires": {} - }, - "csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", - "dev": true, - "requires": { - "css-tree": "^1.1.2" - } - }, - "cssom": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", - "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", - "dev": true - }, - "cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, - "requires": { - "cssom": "~0.3.6" - }, - "dependencies": { - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - } - } - }, - "csstype": { - "version": "2.6.19", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.19.tgz", - "integrity": "sha512-ZVxXaNy28/k3kJg0Fou5MiYpp88j7H9hLZp8PDC3jV0WFjfH5E9xHb56L0W59cPbKbcHXeP4qyT8PrHp8t6LcQ==" - }, - "data-urls": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", - "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", - "dev": true, - "requires": { - "abab": "^2.0.6", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^11.0.0" - }, - "dependencies": { - "tr46": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", - "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", - "dev": true, - "requires": { - "punycode": "^2.1.1" - } - }, - "webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true - }, - "whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", - "dev": true, - "requires": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" - } - } - } - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "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 - }, - "dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true - }, - "deep-equal": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", - "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", - "dev": true, - "requires": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", - "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.2.0" - } - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true - }, - "default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dev": true, - "requires": { - "execa": "^5.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "requires": { - "clone": "^1.0.2" - } - }, - "define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true - }, - "define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", - "requires": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - } - }, - "del": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", - "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", - "dev": true, - "requires": { - "globby": "^11.0.1", - "graceful-fs": "^4.2.4", - "is-glob": "^4.0.1", - "is-path-cwd": "^2.2.0", - "is-path-inside": "^3.0.2", - "p-map": "^4.0.0", - "rimraf": "^3.0.2", - "slash": "^3.0.0" - }, - "dependencies": { - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - } - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "des.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", - "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, - "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 - }, - "detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true - }, - "diff-sequences": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", - "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", - "dev": true - }, - "diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "requires": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - } - } - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "dns-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", - "dev": true - }, - "dns-packet": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz", - "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==", - "dev": true, - "requires": { - "ip": "^1.1.0", - "safe-buffer": "^5.0.1" - } - }, - "dns-txt": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", - "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", - "dev": true, - "requires": { - "buffer-indexof": "^1.0.0" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", - "dev": true, - "requires": { - "utila": "~0.4" - } - }, - "dom-serializer": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", - "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - } - }, - "domain-browser": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-4.22.0.tgz", - "integrity": "sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw==" - }, - "domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", - "dev": true - }, - "domexception": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", - "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", - "dev": true, - "requires": { - "webidl-conversions": "^7.0.0" - }, - "dependencies": { - "webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true - } - } - }, - "domhandler": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz", - "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==", - "dev": true, - "requires": { - "domelementtype": "^2.2.0" - } - }, - "domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - } - }, - "dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - } - } - }, - "dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", - "dev": true - }, - "dotenv-expand": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", - "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", - "dev": true - }, - "duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true - }, - "eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "easy-stack": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/easy-stack/-/easy-stack-1.0.1.tgz", - "integrity": "sha512-wK2sCs4feiiJeFXn3zvY0p41mdU5VUgbgs1rNsc/y5ngFUijdWd+iIN8eoyuZHKB8xN6BL4PdWmzqFmxNg6V2w==", - "dev": true - }, - "editorconfig": { - "version": "0.15.3", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", - "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", - "dev": true, - "requires": { - "commander": "^2.19.0", - "lru-cache": "^4.1.5", - "semver": "^5.6.0", - "sigmund": "^1.0.1" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "dev": true - } - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "electron-to-chromium": { - "version": "1.4.176", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.176.tgz", - "integrity": "sha512-92JdgyRlcNDwuy75MjuFSb3clt6DGJ2IXSpg0MCjKd3JV9eSmuUAIyWiGAp/EtT0z2D4rqbYqThQLV90maH3Zw==" - }, - "elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "requires": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - } - } - }, - "emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "enhanced-resolve": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.14.0.tgz", - "integrity": "sha512-+DCows0XNwLDcUhbFJPdlQEVnT2zXlCv7hPxemTz86/O+B/hCQ+mb7ydkPKiflpVraqLPCAfu7lDy+hBXueojw==", - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "dependencies": { - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" - } - } - }, - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "error-stack-parser": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.6.tgz", - "integrity": "sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ==", - "dev": true, - "requires": { - "stackframe": "^1.1.1" - } - }, - "es-abstract": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", - "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "regexp.prototype.flags": "^1.4.3", - "string.prototype.trimend": "^1.0.5", - "string.prototype.trimstart": "^1.0.5", - "unbox-primitive": "^1.0.2" - } - }, - "es-module-lexer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.2.1.tgz", - "integrity": "sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==" - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es6-object-assign": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", - "integrity": "sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==" - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "dev": true, - "requires": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - } - } - }, - "eslint": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz", - "integrity": "sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==", - "dev": true, - "requires": { - "@eslint/eslintrc": "^2.0.0", - "@eslint/js": "8.35.0", - "@humanwhocodes/config-array": "^0.11.8", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.4.0", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "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 - }, - "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "globals": { - "version": "13.19.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", - "integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "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 - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "eslint-config-prettier": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.4.0.tgz", - "integrity": "sha512-CFotdUcMY18nGRo5KGsnNxpznzhkopOcOo0InID+sgQssPrzjvsyKZPvOgymTFeHrFuC3Tzdf2YndhXtULK9Iw==", - "dev": true, - "requires": {} - }, - "eslint-plugin-prettier": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", - "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0" - } - }, - "eslint-plugin-vue": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-8.7.1.tgz", - "integrity": "sha512-28sbtm4l4cOzoO1LtzQPxfxhQABararUb1JtqusQqObJpWX2e/gmVyeYVfepizPFne0Q5cILkYGiBoV36L12Wg==", - "dev": true, - "requires": { - "eslint-utils": "^3.0.0", - "natural-compare": "^1.4.0", - "nth-check": "^2.0.1", - "postcss-selector-parser": "^6.0.9", - "semver": "^7.3.5", - "vue-eslint-parser": "^8.0.1" - }, - "dependencies": { - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "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==", - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true - }, - "eslint-webpack-plugin": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-3.1.1.tgz", - "integrity": "sha512-xSucskTN9tOkfW7so4EaiFIkulWLXwCB/15H917lR6pTv0Zot6/fetFucmENRb7J5whVSFKIvwnrnsa78SG2yg==", - "dev": true, - "requires": { - "@types/eslint": "^7.28.2", - "jest-worker": "^27.3.1", - "micromatch": "^4.0.4", - "normalize-path": "^3.0.0", - "schema-utils": "^3.1.1" - }, - "dependencies": { - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - } - } - }, - "espree": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", - "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", - "dev": true, - "requires": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" - }, - "estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true - }, - "event-pubsub": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/event-pubsub/-/event-pubsub-4.3.0.tgz", - "integrity": "sha512-z7IyloorXvKbFx9Bpie2+vMJKKx1fH1EN5yiTfp8CiLOTptSYy1g8H4yDpGlEdshL1PBiFtBHepF2cNsqeEeFQ==", - "dev": true - }, - "event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" - }, - "eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" - }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "requires": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true - }, - "expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", - "dev": true, - "requires": { - "@jest/expect-utils": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0" - } - }, - "express": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", - "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", - "dev": true, - "requires": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.19.2", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.4.2", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.9.7", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.17.2", - "serve-static": "1.14.2", - "setprototypeof": "1.2.0", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "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==" - }, - "fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "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==" - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - }, - "fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, - "requires": { - "bser": "2.1.1" - } - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "filter-obj": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-2.0.2.tgz", - "integrity": "sha512-lO3ttPjHZRfjMcxWKb1j1eDhTFsu4meeR3lnMcnBFhk6RuLhvEiuALu2TlfL310ph4lCYYwgF/ElIjdP739tdg==" - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "find-cache-dir": { - "version": "3.3.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, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", - "dev": true - }, - "follow-redirects": { - "version": "1.14.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", - "dev": true - }, - "for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "requires": { - "is-callable": "^1.1.3" - } - }, - "fork-ts-checker-webpack-plugin": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz", - "integrity": "sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@types/json-schema": "^7.0.5", - "chalk": "^4.1.0", - "chokidar": "^3.4.2", - "cosmiconfig": "^6.0.0", - "deepmerge": "^4.2.2", - "fs-extra": "^9.0.0", - "glob": "^7.1.6", - "memfs": "^3.1.2", - "minimatch": "^3.0.4", - "schema-utils": "2.7.0", - "semver": "^7.3.2", - "tapable": "^1.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "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 - }, - "schema-utils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", - "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.4", - "ajv": "^6.12.2", - "ajv-keywords": "^3.4.1" - } - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true - }, - "fraction.js": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.3.tgz", - "integrity": "sha512-pUHWWt6vHzZZiQJcM6S/0PXfS+g6FM4BF5rj9wZyreivhQPdsh5PpE25VtSNxq80wHS5RfY51Ii+8Z0Zl/pmzg==", - "dev": true - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true - }, - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "fs-monkey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", - "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - } - }, - "functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" - }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, - "gitart-vue-dialog": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/gitart-vue-dialog/-/gitart-vue-dialog-2.4.1.tgz", - "integrity": "sha512-eVYQiHhCRtw4fR7eCUbD4Sj3KDF8ZJt22We1SOkHsdbEAzjwqgjAiYAAgKcLT16FXMjURv8XSWDLU8VNL9Nf3A==", - "requires": {} - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "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==" - }, - "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 - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "dependencies": { - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - } - } - }, - "graceful-fs": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", - "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" - }, - "grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, - "gzip-size": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", - "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", - "dev": true, - "requires": { - "duplexer": "^0.1.2" - } - }, - "handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "requires": { - "get-intrinsic": "^1.1.1" - } - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" - }, - "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "requires": { - "has-symbols": "^1.0.2" - } - }, - "hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "requires": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "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==" - } - } - }, - "hash-sum": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz", - "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==", - "dev": true - }, - "hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "highlight.js": { - "version": "11.7.0", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.7.0.tgz", - "integrity": "sha512-1rRqesRFhMO/PRF+G86evnyJkCgaZFOI+Z6kdj15TA18funfoqJXvgPCLSf0SWq3SRfg1j3HlDs8o4s3EGq1oQ==" - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", - "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "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 - }, - "hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - } - }, - "html-encoding-sniffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", - "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", - "dev": true, - "requires": { - "whatwg-encoding": "^2.0.0" - } - }, - "html-entities": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", - "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", - "dev": true - }, - "html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", - "dev": true, - "requires": { - "camel-case": "^4.1.2", - "clean-css": "^5.2.2", - "commander": "^8.3.0", - "he": "^1.2.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.10.0" - } - }, - "html-tags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz", - "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==", - "dev": true - }, - "html-webpack-plugin": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz", - "integrity": "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==", - "dev": true, - "requires": { - "@types/html-minifier-terser": "^6.0.0", - "html-minifier-terser": "^6.0.2", - "lodash": "^4.17.21", - "pretty-error": "^4.0.0", - "tapable": "^2.0.0" - }, - "dependencies": { - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - } - } - }, - "htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", - "dev": true - }, - "http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - } - }, - "http-parser-js": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.5.tgz", - "integrity": "sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA==", - "dev": true - }, - "http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "requires": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - } - }, - "http-proxy-middleware": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.3.tgz", - "integrity": "sha512-1bloEwnrHMnCoO/Gcwbz7eSVvW50KPES01PecpagI+YLNLci4AcuKJrujW4Mc3sBLpFxMSlsLNHS5Nl/lvrTPA==", - "dev": true, - "requires": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - } - }, - "https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==" - }, - "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, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "requires": {} - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - }, - "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true - }, - "immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", - "requires": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - } - }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true - }, - "ipaddr.js": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", - "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==", - "dev": true - }, - "is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "requires": { - "has-bigints": "^1.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==" - }, - "is-ci": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", - "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", - "dev": true, - "requires": { - "ci-info": "^1.5.0" - } - }, - "is-core-module": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", - "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-file-esm": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-file-esm/-/is-file-esm-1.0.0.tgz", - "integrity": "sha512-rZlaNKb4Mr8WlRu2A9XdeoKgnO5aA53XdPHgCKVyCrQ/rWi89RET1+bq37Ru46obaQXeiX4vmFIm1vks41hoSA==", - "dev": true, - "requires": { - "read-pkg-up": "^7.0.1" - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-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 - }, - "is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true - }, - "is-nan": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", - "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" - } - }, - "is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==" - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, - "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "requires": { - "has-symbols": "^1.0.2" - } - }, - "is-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz", - "integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==", - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.20.0", - "for-each": "^0.3.3", - "has-tostringtag": "^1.0.0" - } - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, - "is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "requires": { - "is-docker": "^2.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "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, - "requires": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - } - }, - "istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "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, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - } - }, - "istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, - "javascript-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-2.1.0.tgz", - "integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==", - "dev": true - }, - "jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.5.0.tgz", - "integrity": "sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==", - "dev": true, - "requires": { - "@jest/core": "^29.5.0", - "@jest/types": "^29.5.0", - "import-local": "^3.0.2", - "jest-cli": "^29.5.0" - } - }, - "jest-changed-files": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", - "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", - "dev": true, - "requires": { - "execa": "^5.0.0", - "p-limit": "^3.1.0" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "jest-circus": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.5.0.tgz", - "integrity": "sha512-gq/ongqeQKAplVxqJmbeUOJJKkW3dDNPY8PjhJ5G0lBRvu0e3EWGxGy5cI4LAGA7gV2UHCtWBI4EMXK8c9nQKA==", - "dev": true, - "requires": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^0.7.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.5.0", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.5.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "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 - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-cli": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.5.0.tgz", - "integrity": "sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==", - "dev": true, - "requires": { - "@jest/core": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "import-local": "^3.0.2", - "jest-config": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "prompts": "^2.0.1", - "yargs": "^17.3.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", - "dev": true, - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - } - } - }, - "jest-config": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.5.0.tgz", - "integrity": "sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.5.0", - "@jest/types": "^29.5.0", - "babel-jest": "^29.5.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.5.0", - "jest-environment-node": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.5.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", - "dev": true - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "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 - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-diff": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", - "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^29.4.3", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-docblock": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz", - "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==", - "dev": true, - "requires": { - "detect-newline": "^3.0.0" - } - }, - "jest-each": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.5.0.tgz", - "integrity": "sha512-HM5kIJ1BTnVt+DQZ2ALp3rzXEl+g726csObrW/jpEGl+CDSSQpOJJX2KE/vEg8cxcMXdyEPu6U4QX5eruQv5hA==", - "dev": true, - "requires": { - "@jest/types": "^29.5.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", - "jest-util": "^29.5.0", - "pretty-format": "^29.5.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-environment-jsdom": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.5.0.tgz", - "integrity": "sha512-/KG8yEK4aN8ak56yFVdqFDzKNHgF4BAymCx2LbPNPsUshUlfAl0eX402Xm1pt+eoG9SLZEUVifqXtX8SK74KCw==", - "dev": true, - "requires": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/jsdom": "^20.0.0", - "@types/node": "*", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0", - "jsdom": "^20.0.0" - } - }, - "jest-environment-node": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.5.0.tgz", - "integrity": "sha512-ExxuIK/+yQ+6PRGaHkKewYtg6hto2uGCgvKdb2nfJfKXgZ17DfXjvbZ+jA1Qt9A8EQSfPnt5FKIfnOO3u1h9qw==", - "dev": true, - "requires": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0" - } - }, - "jest-get-type": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", - "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", - "dev": true - }, - "jest-haste-map": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.5.0.tgz", - "integrity": "sha512-IspOPnnBro8YfVYSw6yDRKh/TiCdRngjxeacCps1cQ9cgVN6+10JUcuJ1EabrgYLOATsIAigxA0rLR9x/YlrSA==", - "dev": true, - "requires": { - "@jest/types": "^29.5.0", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "jest-worker": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", - "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", - "dev": true, - "requires": { - "@types/node": "*", - "jest-util": "^29.5.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - } - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-leak-detector": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.5.0.tgz", - "integrity": "sha512-u9YdeeVnghBUtpN5mVxjID7KbkKE1QU4f6uUwuxiY0vYRi9BUCLKlPEZfDGR67ofdFmDz9oPAy2G92Ujrntmow==", - "dev": true, - "requires": { - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" - } - }, - "jest-matcher-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz", - "integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^29.5.0", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-message-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", - "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.5.0", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "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 - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-mock": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.5.0.tgz", - "integrity": "sha512-GqOzvdWDE4fAV2bWQLQCkujxYWL7RxjCnj71b5VhDAGOevB3qj3Ovg26A5NI84ZpODxyzaozXLOh2NCgkbvyaw==", - "dev": true, - "requires": { - "@jest/types": "^29.5.0", - "@types/node": "*", - "jest-util": "^29.5.0" - } - }, - "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, - "requires": {} - }, - "jest-regex-util": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz", - "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==", - "dev": true - }, - "jest-resolve": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.5.0.tgz", - "integrity": "sha512-1TzxJ37FQq7J10jPtQjcc+MkCkE3GBpBecsSUWJ0qZNJpmg6m0D9/7II03yJulm3H/fvVjgqLh/k2eYg+ui52w==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "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 - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-resolve-dependencies": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.5.0.tgz", - "integrity": "sha512-sjV3GFr0hDJMBpYeUuGduP+YeCRbd7S/ck6IvL3kQ9cpySYKqcqhdLLC2rFwrcL7tz5vYibomBrsFYWkIGGjOg==", - "dev": true, - "requires": { - "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.5.0" - } - }, - "jest-runner": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.5.0.tgz", - "integrity": "sha512-m7b6ypERhFghJsslMLhydaXBiLf7+jXy8FwGRHO3BGV1mcQpPbwiqiKUR2zU2NJuNeMenJmlFZCsIqzJCTeGLQ==", - "dev": true, - "requires": { - "@jest/console": "^29.5.0", - "@jest/environment": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-leak-detector": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-resolve": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-util": "^29.5.0", - "jest-watcher": "^29.5.0", - "jest-worker": "^29.5.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "jest-worker": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", - "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", - "dev": true, - "requires": { - "@types/node": "*", - "jest-util": "^29.5.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-runtime": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.5.0.tgz", - "integrity": "sha512-1Hr6Hh7bAgXQP+pln3homOiEZtCDZFqwmle7Ew2j8OlbkIu6uE3Y/etJQG8MLQs3Zy90xrp2C0BRrtPHG4zryw==", - "dev": true, - "requires": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/globals": "^29.5.0", - "@jest/source-map": "^29.4.3", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "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 - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-snapshot": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.5.0.tgz", - "integrity": "sha512-x7Wolra5V0tt3wRs3/ts3S6ciSQVypgGQlJpz2rsdQYoUKxMxPNaoHMGJN6qAuPJqS+2iQ1ZUn5kl7HCyls84g==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/babel__traverse": "^7.0.6", - "@types/prettier": "^2.1.5", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.5.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.5.0", - "semver": "^7.3.5" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "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 - }, - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-transform-stub": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/jest-transform-stub/-/jest-transform-stub-2.0.0.tgz", - "integrity": "sha512-lspHaCRx/mBbnm3h4uMMS3R5aZzMwyNpNIJLXj4cEsV0mIUtS4IjYJLSoyjRCtnxb6RIGJ4NL2quZzfIeNhbkg==", - "dev": true - }, - "jest-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", - "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", - "dev": true, - "requires": { - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "ci-info": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.1.tgz", - "integrity": "sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==", - "dev": true - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-validate": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.5.0.tgz", - "integrity": "sha512-pC26etNIi+y3HV8A+tUGr/lph9B18GnzSRAkPaaZJIE1eFdiYm6/CewuiJQ8/RlfHd1u/8Ioi8/sJ+CmbA+zAQ==", - "dev": true, - "requires": { - "@jest/types": "^29.5.0", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", - "leven": "^3.1.0", - "pretty-format": "^29.5.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-watcher": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.5.0.tgz", - "integrity": "sha512-KmTojKcapuqYrKDpRwfqcQ3zjMlwu27SYext9pt4GlF5FUgB+7XE1mcCnSm6a4uUpFyQIkb6ZhzZvHl+jiBCiA==", - "dev": true, - "requires": { - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.5.0", - "string-length": "^4.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-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==", - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "joi": { - "version": "17.6.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.6.0.tgz", - "integrity": "sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw==", - "dev": true, - "requires": { - "@hapi/hoek": "^9.0.0", - "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.3", - "@sideway/formula": "^3.0.0", - "@sideway/pinpoint": "^2.0.0" - } - }, - "js-beautify": { - "version": "1.14.6", - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.6.tgz", - "integrity": "sha512-GfofQY5zDp+cuHc+gsEXKPpNw2KbPddreEo35O6jT6i0RVK6LhsoYBhq5TvK4/n74wnA0QbK8gGd+jUZwTMKJw==", - "dev": true, - "requires": { - "config-chain": "^1.1.13", - "editorconfig": "^0.15.3", - "glob": "^8.0.3", - "nopt": "^6.0.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "js-message": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.7.tgz", - "integrity": "sha512-efJLHhLjIyKRewNS9EGZ4UpI8NguuL6fKkhRxVuMmrGV2xN/0APGdQYwLFky5w9naebSZ0OwAGp0G6/2Cg90rA==", - "dev": true - }, - "js-sdsl": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz", - "integrity": "sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw==", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "jsdom": { - "version": "20.0.3", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", - "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", - "dev": true, - "requires": { - "abab": "^2.0.6", - "acorn": "^8.8.1", - "acorn-globals": "^7.0.0", - "cssom": "^0.5.0", - "cssstyle": "^2.3.0", - "data-urls": "^3.0.2", - "decimal.js": "^10.4.2", - "domexception": "^4.0.0", - "escodegen": "^2.0.0", - "form-data": "^4.0.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.1", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.2", - "parse5": "^7.1.1", - "saxes": "^6.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.2", - "w3c-xmlserializer": "^4.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^2.0.0", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^11.0.0", - "ws": "^8.11.0", - "xml-name-validator": "^4.0.0" - }, - "dependencies": { - "entities": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", - "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", - "dev": true - }, - "parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, - "requires": { - "entities": "^4.4.0" - } - }, - "tr46": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", - "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", - "dev": true, - "requires": { - "punycode": "^2.1.1" - } - }, - "webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true - }, - "whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", - "dev": true, - "requires": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" - } - }, - "ws": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.0.tgz", - "integrity": "sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==", - "dev": true, - "requires": {} - } - } - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" - }, - "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==" - }, - "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": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "jszip": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", - "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", - "requires": { - "lie": "~3.3.0", - "pako": "~1.0.2", - "readable-stream": "~2.3.6", - "setimmediate": "^1.0.5" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true - }, - "klona": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", - "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", - "dev": true - }, - "launch-editor": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.2.1.tgz", - "integrity": "sha512-On+V7K2uZK6wK7x691ycSUbLD/FyKKelArkbaAMSSJU8JmqmhwN2+mnJDNINuJWSrh2L0kDk+ZQtbC/gOWUwLw==", - "dev": true, - "requires": { - "chalk": "^2.3.0", - "shell-quote": "^1.6.1" - } - }, - "launch-editor-middleware": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/launch-editor-middleware/-/launch-editor-middleware-2.2.1.tgz", - "integrity": "sha512-s0UO2/gEGiCgei3/2UN3SMuUj1phjQN8lcpnvgLSz26fAzNWPQ6Nf/kF5IFClnfU2ehp6LrmKdMU/beveO+2jg==", - "dev": true, - "requires": { - "launch-editor": "^2.2.1" - } - }, - "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 - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "lie": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", - "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", - "requires": { - "immediate": "~3.0.5" - } - }, - "lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true - }, - "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "lint-staged": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.2.0.tgz", - "integrity": "sha512-GbyK5iWinax5Dfw5obm2g2ccUiZXNGtAS4mCbJ0Lv4rq6iEtfBSjOYdcbOtAIFtM114t0vdpViDDetjVTSd8Vw==", - "dev": true, - "requires": { - "chalk": "5.2.0", - "cli-truncate": "^3.1.0", - "commander": "^10.0.0", - "debug": "^4.3.4", - "execa": "^7.0.0", - "lilconfig": "2.1.0", - "listr2": "^5.0.7", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-inspect": "^1.12.3", - "pidtree": "^0.6.0", - "string-argv": "^0.3.1", - "yaml": "^2.2.1" - }, - "dependencies": { - "chalk": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", - "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", - "dev": true - }, - "commander": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.0.tgz", - "integrity": "sha512-zS5PnTI22FIRM6ylNW8G4Ap0IEOyk62fhLSD0+uHRT9McRCLGpkVNvao4bjimpK/GShynyQkFFxHhwMcETmduA==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "execa": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz", - "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "human-signals": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.0.tgz", - "integrity": "sha512-zyzVyMjpGBX2+6cDVZeFPCdtOtdsxOeseRhB9tkQ6xXmGUNrcnBzdEKPy3VPNYz+4gy1oukVOXcrJCunSyc6QQ==", - "dev": true - }, - "is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true - }, - "mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true - }, - "npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", - "dev": true, - "requires": { - "path-key": "^4.0.0" - }, - "dependencies": { - "path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true - } - } - }, - "onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "requires": { - "mimic-fn": "^4.0.0" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "yaml": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz", - "integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==", - "dev": true - } - } - }, - "listr2": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-5.0.8.tgz", - "integrity": "sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA==", - "dev": true, - "requires": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.19", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.8.0", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, - "requires": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - } - } - }, - "loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==" - }, - "loader-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", - "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "dependencies": { - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - } - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "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==" - }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true - }, - "lodash.defaultsdeep": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz", - "integrity": "sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==", - "dev": true - }, - "lodash.kebabcase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", - "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", - "dev": true - }, - "lodash.mapvalues": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", - "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=", - "dev": true - }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true - }, - "lodash.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 - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", - "dev": true - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "dev": true, - "requires": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - } - } - }, - "lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dev": true, - "requires": { - "tslib": "^2.0.3" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - } - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", - "requires": { - "sourcemap-codec": "^1.4.8" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "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 - }, - "makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "requires": { - "tmpl": "1.0.5" - } - }, - "md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", - "dev": true - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true - }, - "memfs": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz", - "integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==", - "dev": true, - "requires": { - "fs-monkey": "1.0.3" - } - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "merge-source-map": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", - "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", - "dev": true, - "requires": { - "source-map": "^0.6.1" - } - }, - "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==" - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "requires": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - } - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" - }, - "mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "requires": { - "mime-db": "1.51.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "mini-css-extract-plugin": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.5.3.tgz", - "integrity": "sha512-YseMB8cs8U/KCaAGQoqYmfUuhhGW0a9p9XvWXrxVOkE3/IiISTLw4ALNt7JR5B2eYauFM+PQGSbXMDmVbR7Tfw==", - "dev": true, - "requires": { - "schema-utils": "^4.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - } - } - } - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true - }, - "minipass": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz", - "integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "mitt": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mitt/-/mitt-2.1.0.tgz", - "integrity": "sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg==" - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "module-alias": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/module-alias/-/module-alias-2.2.2.tgz", - "integrity": "sha512-A/78XjoX2EmNvppVWEhM2oGk3x4lLxnkEA4jTbaK97QKSDjkIoOsKQlfylt/d3kKKi596Qy3NP5XrXJ6fZIC9Q==", - "dev": true - }, - "mrmime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz", - "integrity": "sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "multicast-dns": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", - "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", - "dev": true, - "requires": { - "dns-packet": "^1.3.1", - "thunky": "^1.0.2" - } - }, - "multicast-dns-service-types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", - "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", - "dev": true - }, - "mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "requires": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "nanoid": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", - "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==" - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dev": true, - "requires": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - } - } - }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true - }, - "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-polyfill-webpack-plugin": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/node-polyfill-webpack-plugin/-/node-polyfill-webpack-plugin-2.0.1.tgz", - "integrity": "sha512-ZUMiCnZkP1LF0Th2caY6J/eKKoA0TefpoVa68m/LQU1I/mE8rGt4fNYGgNuCcK+aG8P8P43nbeJ2RqJMOL/Y1A==", - "requires": { - "assert": "^2.0.0", - "browserify-zlib": "^0.2.0", - "buffer": "^6.0.3", - "console-browserify": "^1.2.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.12.0", - "domain-browser": "^4.22.0", - "events": "^3.3.0", - "filter-obj": "^2.0.2", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "^1.0.1", - "process": "^0.11.10", - "punycode": "^2.1.1", - "querystring-es3": "^0.2.1", - "readable-stream": "^4.0.0", - "stream-browserify": "^3.0.0", - "stream-http": "^3.2.0", - "string_decoder": "^1.3.0", - "timers-browserify": "^2.0.12", - "tty-browserify": "^0.0.1", - "type-fest": "^2.14.0", - "url": "^0.11.0", - "util": "^0.12.4", - "vm-browserify": "^1.1.2" - }, - "dependencies": { - "buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "readable-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.1.0.tgz", - "integrity": "sha512-sVisi3+P2lJ2t0BPbpK629j8wRW06yKGJUcaLAGXPAUhyUxVJm7VsCTit1PFgT4JHUDMrGNR+ZjSKpzGaRF3zw==", - "requires": { - "abort-controller": "^3.0.0" - } - }, - "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==" - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "type-fest": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.18.0.tgz", - "integrity": "sha512-pRS+/yrW5TjPPHNOvxhbNZexr2bS63WjrMU8a+VzEBhUi9Tz1pZeD+vQz3ut0svZ46P+SRqMEPnJmk2XnvNzTw==" - } - } - }, - "node-releases": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz", - "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==" - }, - "nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", - "dev": true, - "requires": { - "abbrev": "^1.0.0" - } - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true - }, - "normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "^2.0.0" - } - }, - "nth-check": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", - "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", - "dev": true, - "requires": { - "boolbase": "^1.0.0" - } - }, - "nwsapi": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.2.tgz", - "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==" - }, - "object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - }, - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - }, - "obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "open": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", - "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", - "dev": true, - "requires": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - } - }, - "opener": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", - "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", - "dev": true - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "requires": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==" - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "p-retry": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.1.tgz", - "integrity": "sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA==", - "dev": true, - "requires": { - "@types/retry": "^0.12.0", - "retry": "^0.13.1" - } - }, - "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 - }, - "pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" - }, - "param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dev": true, - "requires": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - } - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", - "requires": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "parse5": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", - "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", - "dev": true - }, - "parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "requires": { - "parse5": "^6.0.1" - }, - "dependencies": { - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - } - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true - }, - "pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dev": true, - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - } - } - }, - "path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "pidtree": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", - "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", - "dev": true - }, - "pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "dev": true - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - } - }, - "portfinder": { - "version": "1.0.28", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", - "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", - "dev": true, - "requires": { - "async": "^2.6.2", - "debug": "^3.1.1", - "mkdirp": "^0.5.5" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "postcss": { - "version": "8.4.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.6.tgz", - "integrity": "sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA==", - "requires": { - "nanoid": "^3.2.0", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - } - }, - "postcss-calc": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", - "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.9", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-colormin": { - "version": "5.2.5", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.2.5.tgz", - "integrity": "sha512-+X30aDaGYq81mFqwyPpnYInsZQnNpdxMX0ajlY7AExCexEFkPVV+KrO7kXwayqEWL2xwEbNQ4nUO0ZsRWGnevg==", - "dev": true, - "requires": { - "browserslist": "^4.16.6", - "caniuse-api": "^3.0.0", - "colord": "^2.9.1", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-convert-values": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.0.4.tgz", - "integrity": "sha512-bugzSAyjIexdObovsPZu/sBCTHccImJxLyFgeV0MmNBm/Lw5h5XnjfML6gzEmJ3A6nyfCW7hb1JXzcsA4Zfbdw==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-discard-comments": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.0.3.tgz", - "integrity": "sha512-6W5BemziRoqIdAKT+1QjM4bNcJAQ7z7zk073730NHg4cUXh3/rQHHj7pmYxUB9aGhuRhBiUf0pXvIHkRwhQP0Q==", - "dev": true, - "requires": {} - }, - "postcss-discard-duplicates": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.3.tgz", - "integrity": "sha512-vPtm1Mf+kp7iAENTG7jI1MN1lk+fBqL5y+qxyi4v3H+lzsXEdfS3dwUZD45KVhgzDEgduur8ycB4hMegyMTeRw==", - "dev": true, - "requires": {} - }, - "postcss-discard-empty": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.0.3.tgz", - "integrity": "sha512-xGJugpaXKakwKI7sSdZjUuN4V3zSzb2Y0LOlmTajFbNinEjTfVs9PFW2lmKBaC/E64WwYppfqLD03P8l9BuueA==", - "dev": true, - "requires": {} - }, - "postcss-discard-overridden": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.0.4.tgz", - "integrity": "sha512-3j9QH0Qh1KkdxwiZOW82cId7zdwXVQv/gRXYDnwx5pBtR1sTkU4cXRK9lp5dSdiM0r0OICO/L8J6sV1/7m0kHg==", - "dev": true, - "requires": {} - }, - "postcss-loader": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", - "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", - "dev": true, - "requires": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.5", - "semver": "^7.3.5" - }, - "dependencies": { - "cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", - "dev": true, - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - } - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "postcss-merge-longhand": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.0.6.tgz", - "integrity": "sha512-rkmoPwQO6ymJSmWsX6l2hHeEBQa7C4kJb9jyi5fZB1sE8nSCv7sqchoYPixRwX/yvLoZP2y6FA5kcjiByeJqDg==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0", - "stylehacks": "^5.0.3" - } - }, - "postcss-merge-rules": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.0.6.tgz", - "integrity": "sha512-nzJWJ9yXWp8AOEpn/HFAW72WKVGD2bsLiAmgw4hDchSij27bt6TF+sIK0cJUBAYT3SGcjtGGsOR89bwkkMuMgQ==", - "dev": true, - "requires": { - "browserslist": "^4.16.6", - "caniuse-api": "^3.0.0", - "cssnano-utils": "^3.0.2", - "postcss-selector-parser": "^6.0.5" - } - }, - "postcss-minify-font-values": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.0.4.tgz", - "integrity": "sha512-RN6q3tyuEesvyCYYFCRGJ41J1XFvgV+dvYGHr0CeHv8F00yILlN8Slf4t8XW4IghlfZYCeyRrANO6HpJ948ieA==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-minify-gradients": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.0.6.tgz", - "integrity": "sha512-E/dT6oVxB9nLGUTiY/rG5dX9taugv9cbLNTFad3dKxOO+BQg25Q/xo2z2ddG+ZB1CbkZYaVwx5blY8VC7R/43A==", - "dev": true, - "requires": { - "colord": "^2.9.1", - "cssnano-utils": "^3.0.2", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-minify-params": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.0.5.tgz", - "integrity": "sha512-YBNuq3Rz5LfLFNHb9wrvm6t859b8qIqfXsWeK7wROm3jSKNpO1Y5e8cOyBv6Acji15TgSrAwb3JkVNCqNyLvBg==", - "dev": true, - "requires": { - "browserslist": "^4.16.6", - "cssnano-utils": "^3.0.2", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-minify-selectors": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.1.3.tgz", - "integrity": "sha512-9RJfTiQEKA/kZhMaEXND893nBqmYQ8qYa/G+uPdVnXF6D/FzpfI6kwBtWEcHx5FqDbA79O9n6fQJfrIj6M8jvQ==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.5" - } - }, - "postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true, - "requires": {} - }, - "postcss-modules-local-by-default": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", - "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", - "dev": true, - "requires": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - } - }, - "postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.4" - } - }, - "postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, - "requires": { - "icss-utils": "^5.0.0" - } - }, - "postcss-normalize-charset": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.0.3.tgz", - "integrity": "sha512-iKEplDBco9EfH7sx4ut7R2r/dwTnUqyfACf62Unc9UiyFuI7uUqZZtY+u+qp7g8Qszl/U28HIfcsI3pEABWFfA==", - "dev": true, - "requires": {} - }, - "postcss-normalize-display-values": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.3.tgz", - "integrity": "sha512-FIV5FY/qs4Ja32jiDb5mVj5iWBlS3N8tFcw2yg98+8MkRgyhtnBgSC0lxU+16AMHbjX5fbSJgw5AXLMolonuRQ==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-positions": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.0.4.tgz", - "integrity": "sha512-qynirjBX0Lc73ROomZE3lzzmXXTu48/QiEzKgMeqh28+MfuHLsuqC9po4kj84igZqqFGovz8F8hf44hA3dPYmQ==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-repeat-style": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.4.tgz", - "integrity": "sha512-Innt+wctD7YpfeDR7r5Ik6krdyppyAg2HBRpX88fo5AYzC1Ut/l3xaxACG0KsbX49cO2n5EB13clPwuYVt8cMA==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-string": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.0.4.tgz", - "integrity": "sha512-Dfk42l0+A1CDnVpgE606ENvdmksttLynEqTQf5FL3XGQOyqxjbo25+pglCUvziicTxjtI2NLUR6KkxyUWEVubQ==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-timing-functions": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.3.tgz", - "integrity": "sha512-QRfjvFh11moN4PYnJ7hia4uJXeFotyK3t2jjg8lM9mswleGsNw2Lm3I5wO+l4k1FzK96EFwEVn8X8Ojrp2gP4g==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-unicode": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.4.tgz", - "integrity": "sha512-W79Regn+a+eXTzB+oV/8XJ33s3pDyFTND2yDuUCo0Xa3QSy1HtNIfRVPXNubHxjhlqmMFADr3FSCHT84ITW3ig==", - "dev": true, - "requires": { - "browserslist": "^4.16.6", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-url": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.0.5.tgz", - "integrity": "sha512-Ws3tX+PcekYlXh+ycAt0wyzqGthkvVtZ9SZLutMVvHARxcpu4o7vvXcNoiNKyjKuWecnjS6HDI3fjBuDr5MQxQ==", - "dev": true, - "requires": { - "normalize-url": "^6.0.1", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-whitespace": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.4.tgz", - "integrity": "sha512-wsnuHolYZjMwWZJoTC9jeI2AcjA67v4UuidDrPN9RnX8KIZfE+r2Nd6XZRwHVwUiHmRvKQtxiqo64K+h8/imaw==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-ordered-values": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.0.5.tgz", - "integrity": "sha512-mfY7lXpq+8bDEHfP+muqibDPhZ5eP9zgBEF9XRvoQgXcQe2Db3G1wcvjbnfjXG6wYsl+0UIjikqq4ym1V2jGMQ==", - "dev": true, - "requires": { - "cssnano-utils": "^3.0.2", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-reduce-initial": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.0.3.tgz", - "integrity": "sha512-c88TkSnQ/Dnwgb4OZbKPOBbCaauwEjbECP5uAuFPOzQ+XdjNjRH7SG0dteXrpp1LlIFEKK76iUGgmw2V0xeieA==", - "dev": true, - "requires": { - "browserslist": "^4.16.6", - "caniuse-api": "^3.0.0" - } - }, - "postcss-reduce-transforms": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.4.tgz", - "integrity": "sha512-VIJB9SFSaL8B/B7AXb7KHL6/GNNbbCHslgdzS9UDfBZYIA2nx8NLY7iD/BXFSO/1sRUILzBTfHCoW5inP37C5g==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-selector-parser": { - "version": "6.0.9", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz", - "integrity": "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - } - }, - "postcss-svgo": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.0.4.tgz", - "integrity": "sha512-yDKHvULbnZtIrRqhZoA+rxreWpee28JSRH/gy9727u0UCgtpv1M/9WEWY3xySlFa0zQJcqf6oCBJPR5NwkmYpg==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0", - "svgo": "^2.7.0" - } - }, - "postcss-unique-selectors": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.0.4.tgz", - "integrity": "sha512-5ampwoSDJCxDPoANBIlMgoBcYUHnhaiuLYJR5pj1DLnYQvMRVyFuTA5C3Bvt+aHtiqWpJkD/lXT50Vo1D0ZsAQ==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.5" - } - }, - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "prettier": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.6.tgz", - "integrity": "sha512-mtuzdiBbHwPEgl7NxWlqOkithPyp4VN93V7VeHVWBF+ad3I5avc0RVDT4oImXQy9H/AqxA2NSQH8pSxHW6FYbQ==", - "dev": true - }, - "prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "requires": { - "fast-diff": "^1.1.2" - } - }, - "pretty-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", - "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", - "dev": true, - "requires": { - "lodash": "^4.17.20", - "renderkid": "^3.0.0" - } - }, - "pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.4.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "progress-webpack-plugin": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/progress-webpack-plugin/-/progress-webpack-plugin-1.0.12.tgz", - "integrity": "sha512-b0dMK6D7pFicDzSdh+sU0p/gp3n5QAGwjPbgacmYB/eVQpayzf9lKTQLYMnTAbk69fKoXSoVNl/+IkobJblL1A==", - "dev": true, - "requires": { - "chalk": "^2.1.0", - "figures": "^2.0.0", - "log-update": "^2.1.0" - }, - "dependencies": { - "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true - }, - "ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "requires": { - "restore-cursor": "^2.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "log-update": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", - "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", - "dev": true, - "requires": { - "ansi-escapes": "^3.0.0", - "cli-cursor": "^2.0.0", - "wrap-ansi": "^3.0.1" - } - }, - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "wrap-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", - "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0" - } - } - } - }, - "prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "requires": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - } - }, - "proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", - "dev": true - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "dependencies": { - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true - } - } - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true - }, - "public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "requires": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - } - } - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, - "pure-rand": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.0.tgz", - "integrity": "sha512-rLSBxJjP+4DQOgcJAx6RZHT2he2pkhQdSnofG5VWyVl6GRq/K02ISOuOLcsMOrtKDIJb8JN2zm3FFzWNbezdPw==", - "dev": true - }, - "qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", - "dev": true - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==" - }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==" - }, - "querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "requires": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true - }, - "raw-body": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", - "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true - } - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "dependencies": { - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true - } - } - }, - "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "dependencies": { - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - } - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true - }, - "regenerate-unicode-properties": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz", - "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==", - "dev": true, - "requires": { - "regenerate": "^1.4.2" - } - }, - "regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", - "dev": true - }, - "regenerator-transform": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz", - "integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.8.4" - } - }, - "regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" - } - }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, - "regexpu-core": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.1.0.tgz", - "integrity": "sha512-bb6hk+xWd2PEOkj5It46A16zFMs2mv86Iwpdu94la4S3sJ7C973h2dHpYKwIBGaWSO7cIRJ+UX0IeMaWcO4qwA==", - "dev": true, - "requires": { - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.0.1", - "regjsgen": "^0.6.0", - "regjsparser": "^0.8.2", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.0.0" - } - }, - "regjsgen": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz", - "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==", - "dev": true - }, - "regjsparser": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz", - "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "dev": true - } - } - }, - "relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", - "dev": true - }, - "renderkid": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", - "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", - "dev": true, - "requires": { - "css-select": "^4.1.3", - "dom-converter": "^0.2.0", - "htmlparser2": "^6.1.0", - "lodash": "^4.17.21", - "strip-ansi": "^6.0.1" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, - "resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", - "dev": true, - "requires": { - "is-core-module": "^2.8.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "requires": { - "resolve-from": "^5.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - } - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "resolve.exports": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.1.tgz", - "integrity": "sha512-OEJWVeimw8mgQuj3HfkNl4KqRevH7lzeQNaWRPfx0PPse7Jk6ozcsG4FKVgtzDsC1KUF+YlTHh17NcgHOPykLw==", - "dev": true - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "rxjs": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", - "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", - "dev": true, - "requires": { - "tslib": "^2.1.0" - }, - "dependencies": { - "tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", - "dev": true + "type": "consulting", + "url": "https://feross.org/support" } + ], + "dependencies": { + "queue-microtask": "^1.2.2" } }, - "safe-buffer": { + "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==" }, - "safer-buffer": { + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true }, - "saxes": { + "node_modules/saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", "dev": true, - "requires": { + "dependencies": { "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" } }, - "schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, - "requires": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", - "dev": true - }, - "selfsigned": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.0.tgz", - "integrity": "sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ==", + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, - "requires": { - "node-forge": "^1.2.0" + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" } }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "node_modules/semver/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 }, - "send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", - "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "1.8.1", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - } - } - }, - "serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "requires": { - "randombytes": "^2.1.0" - } - }, - "serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - } - } - }, - "serve-static": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", - "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.2" - } - }, - "setimmediate": { + "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" } }, - "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==", + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, - "requires": { - "kind-of": "^6.0.2" + "engines": { + "node": ">=8" } }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "node_modules/shell-quote": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.0.tgz", + "integrity": "sha512-QHsz8GgQIGKlRi24yFc6a6lN69Idnx634w49ay6+jA5yFh7a1UY+4Rp6HPx/L/1zcEDPEij8cIsiqR6bQsE5VQ==", "dev": true, - "requires": { - "shebang-regex": "^1.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "shell-quote": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", - "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", - "dev": true - }, - "side-channel": { + "node_modules/side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "requires": { + "dev": true, + "dependencies": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha512-fCvEXfh6NWpm+YSuY2bpXb/VIihqWA6hLsgboC+0nl71Q7N7o2eaCW8mJa/NLvQhs6jpd3VZV4UiUQlV6+lc8g==", + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true }, - "signal-exit": { + "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 }, - "sirv": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.19.tgz", - "integrity": "sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ==", - "dev": true, - "requires": { - "@polka/url": "^1.0.0-next.20", - "mrmime": "^1.0.0", - "totalist": "^1.0.0" + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "slash": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.0.0.tgz", - "integrity": "sha512-n6KkmvKS0623igEVj3FF0OZs1gYYJ0o0Hj939yc1fyxl2xt+xYpLnzJB6xBSqOfV9ZFLEWodBBN/heZJahuIJQ==" - }, - "slice-ansi": { + "node_modules/slice-ansi": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", "dev": true, - "requires": { + "dependencies": { "ansi-styles": "^6.0.0", "is-fullwidth-code-point": "^4.0.0" }, - "dependencies": { - "ansi-styles": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.1.0.tgz", - "integrity": "sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true - } + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "node_modules/slice-ansi/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, - "requires": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "sortablejs": { + "node_modules/sortablejs": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz", "integrity": "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w==", "peer": true }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "source-map-js": { + "node_modules/source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" - }, - "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==", - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "engines": { + "node": ">=0.10.0" } }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" - }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "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, - "requires": { + "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, - "spdx-exceptions": { + "node_modules/spdx-exceptions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", "dev": true }, - "spdx-expression-parse": { + "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, - "requires": { + "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, - "spdx-license-ids": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", - "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", + "node_modules/spdx-license-ids": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", "dev": true }, - "spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - } - }, - "spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true }, - "stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "node_modules/std-env": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.3.3.tgz", + "integrity": "sha512-Rz6yejtVyWnVjC1RFvNmYL10kgjC49EOghxWn0RFqlCHGFpQx+Xe7yW3I4ceK1SGrWIGMjD5Kbue8W/udkbMJg==", "dev": true }, - "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, - "requires": { - "escape-string-regexp": "^2.0.0" - }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dependencies": { - "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 - } + "safe-buffer": "~5.1.0" } }, - "stackframe": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.0.tgz", - "integrity": "sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA==", - "dev": true - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - }, - "stream-browserify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", - "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", - "requires": { - "inherits": "~2.0.4", - "readable-stream": "^3.5.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "engines": { + "node": ">=0.6.19" } }, - "stream-http": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", - "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", - "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "xtend": "^4.0.2" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "string-argv": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", - "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", - "dev": true + "node_modules/string-width/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, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } }, - "string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "node_modules/string.prototype.padend": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.4.tgz", + "integrity": "sha512-67otBXoksdjsnXXRUq+KMVTdlVRZ2af422Y0aTyTjVaoQkGr3mxl2Bc5emi7dOQ3OGVVQQskmLEWwFXwommpNw==", "dev": true, - "requires": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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/string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "string.prototype.trimend": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", - "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", - "requires": { + "node_modules/string.prototype.trimend": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "dev": true, + "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "string.prototype.trimstart": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", - "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", - "requires": { + "node_modules/string.prototype.trimstart": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "dev": true, + "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "strip-ansi": { + "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, - "requires": { + "dependencies": { "ansi-regex": "^5.0.1" }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - } + "engines": { + "node": ">=8" } }, - "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 - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } }, - "strip-indent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", - "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", - "dev": true + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "strip-json-comments": { + "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "stylehacks": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.0.3.tgz", - "integrity": "sha512-ENcUdpf4yO0E1rubu8rkxI+JGQk4CgjchynZ4bDBJDfqdy+uhTRSWb8/F3Jtu+Bw5MW45Po3/aQGeIyyxgQtxg==", + "node_modules/strip-literal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.0.1.tgz", + "integrity": "sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==", "dev": true, - "requires": { - "browserslist": "^4.16.6", - "postcss-selector-parser": "^6.0.4" + "dependencies": { + "acorn": "^8.8.2" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" } }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/sucrase": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.32.0.tgz", + "integrity": "sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ==", "dev": true, - "requires": { - "has-flag": "^3.0.0" + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "7.1.6", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/sucrase/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "supports-preserve-symlinks-flag": { + "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "svg-tags": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", - "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", - "dev": true - }, - "svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", - "dev": true, - "requires": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" + "dev": true, + "engines": { + "node": ">= 0.4" }, - "dependencies": { - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "symbol-tree": { + "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 }, - "tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "dev": true - }, - "terser": { - "version": "5.17.3", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.17.3.tgz", - "integrity": "sha512-AudpAZKmZHkG9jueayypz4duuCFJMMNGRMwaPvQKWfxKedh8Z2x3OCoDqIIi1xx5+iwx1u6Au8XQcc9Lke65Yg==", - "requires": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - } + "node_modules/synckit": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", + "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", + "dev": true, + "dependencies": { + "@pkgr/utils": "^2.3.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" } }, - "terser-webpack-plugin": { - "version": "5.3.8", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.8.tgz", - "integrity": "sha512-WiHL3ElchZMsK27P8uIUh4604IgJyAW47LVXGbEoB21DbQcZ+OuMpGjVYnEUaqcWM6dO8uS2qUbA7LSCWqvsbg==", - "requires": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.8" - }, - "dependencies": { - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - } - } + "node_modules/synckit/node_modules/tslib": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", + "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==", + "dev": true }, - "test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "node_modules/tailwindcss": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz", + "integrity": "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==", "dev": true, - "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.12", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.18.2", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" } }, - "text-table": { + "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "thenify": { + "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", "dev": true, - "requires": { + "dependencies": { "any-promise": "^1.0.0" } }, - "thenify-all": { + "node_modules/thenify-all": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", "dev": true, - "requires": { + "dependencies": { "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" } }, - "thread-loader": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/thread-loader/-/thread-loader-3.0.4.tgz", - "integrity": "sha512-ByaL2TPb+m6yArpqQUZvP+5S1mZtXsEP7nWKKlAUTm7fCml8kB5s1uI3+eHRP2bk5mVYfRSBI7FFf+tWEyLZwA==", - "dev": true, - "requires": { - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^4.1.0", - "loader-utils": "^2.0.0", - "neo-async": "^2.6.2", - "schema-utils": "^3.0.0" - }, - "dependencies": { - "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, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - } - } - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "node_modules/tinybench": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.0.tgz", + "integrity": "sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA==", "dev": true }, - "timers-browserify": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", - "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", - "requires": { - "setimmediate": "^1.0.4" + "node_modules/tinypool": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.7.0.tgz", + "integrity": "sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==", + "dev": true, + "engines": { + "node": ">=14.0.0" } }, - "timsort": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", - "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", - "dev": true - }, - "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/tinyspy": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.0.tgz", + "integrity": "sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true + "node_modules/titleize": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", + "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "to-regex-range": { + "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, - "requires": { + "dependencies": { "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" } }, - "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 - }, - "totalist": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz", - "integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==", - "dev": true - }, - "tough-cookie": { + "node_modules/tough-cookie": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz", "integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==", "dev": true, - "requires": { + "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", "universalify": "^0.2.0", "url-parse": "^1.5.3" }, - "dependencies": { - "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 - } - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "dev": true - }, - "ts-jest": { - "version": "29.0.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.5.tgz", - "integrity": "sha512-PL3UciSgIpQ7f6XjVOmbi96vmDHUqAyqDr8YxzopDqX3kfgYtX1cuNeBjP+L9sFXi6nzsGGA6R3fP3DDDJyrxA==", - "dev": true, - "requires": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^29.0.0", - "json5": "^2.2.3", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "7.x", - "yargs-parser": "^21.0.1" - }, - "dependencies": { - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - } + "engines": { + "node": ">=6" } }, - "ts-loader": { - "version": "9.2.6", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.2.6.tgz", - "integrity": "sha512-QMTC4UFzHmu9wU2VHZEmWWE9cUajjfcdcws+Gh7FhiO+Dy0RnR1bNz0YCHqhI0yRowCE9arVnNxYHqELOy9Hjw==", + "node_modules/tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", "dev": true, - "requires": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.0.0", - "micromatch": "^4.0.0", - "semver": "^7.3.4" - }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "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 - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "punycode": "^2.3.0" + }, + "engines": { + "node": ">=14" } }, - "tsconfig": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", - "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", + "node_modules/ts-api-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", "dev": true, - "requires": { - "@types/strip-bom": "^3.0.0", - "@types/strip-json-comments": "0.0.30", - "strip-bom": "^3.0.0", - "strip-json-comments": "^2.0.0" + "engines": { + "node": ">=16.13.0" }, - "dependencies": { - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true - } + "peerDependencies": { + "typescript": ">=4.2.0" } }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "dev": true }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, - "tty-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", - "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==" - }, - "type-check": { + "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, - "requires": { + "dependencies": { "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" } }, - "type-detect": { + "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "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 + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "node_modules/typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "devOptional": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" } }, - "typescript": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz", - "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==", + "node_modules/ufo": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.1.tgz", + "integrity": "sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw==", "dev": true }, - "unbox-primitive": { + "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "requires": { + "dev": true, + "dependencies": { "call-bind": "^1.0.2", "has-bigints": "^1.0.2", "has-symbols": "^1.0.3", "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "dev": true - }, - "unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "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, - "requires": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" + "engines": { + "node": ">= 4.0.0" } }, - "unicode-match-property-value-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", - "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", - "dev": true - }, - "unicode-property-aliases-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", - "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", - "dev": true - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "engines": { + "node": ">=8" + } }, - "update-browserslist-db": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.4.tgz", - "integrity": "sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==", - "requires": { + "node_modules/update-browserslist-db": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", + "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "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": { "escalade": "^3.1.1", "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "uri-js": { + "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "requires": { - "punycode": "^2.1.0" - } - }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==", - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, + "dev": true, "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" - } + "punycode": "^2.1.0" } }, - "url-parse": { + "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==", "dev": true, - "requires": { + "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" } }, - "util": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", - "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", - "requires": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "safe-buffer": "^5.1.2", - "which-typed-array": "^1.1.2" - } - }, - "util-deprecate": { + "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", - "dev": true - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true - }, - "v8-to-istanbul": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", - "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" - } - }, - "validate-npm-package-license": { + "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, - "requires": { + "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true - }, - "vm-browserify": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", - "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" - }, - "vue": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.47.tgz", - "integrity": "sha512-60188y/9Dc9WVrAZeUVSDxRQOZ+z+y5nO2ts9jWXSTkMvayiWxCWOWtBQoYjLeccfXkiiPZWAHcV+WTPhkqJHQ==", - "requires": { - "@vue/compiler-dom": "3.2.47", - "@vue/compiler-sfc": "3.2.47", - "@vue/runtime-dom": "3.2.47", - "@vue/server-renderer": "3.2.47", - "@vue/shared": "3.2.47" - } - }, - "vue-chart-3": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/vue-chart-3/-/vue-chart-3-3.1.8.tgz", - "integrity": "sha512-zX5ajjQi/PocEqLETlej3vp92q/tnI/Fvu2RVb++Kap8qOrXu6PXCpodi73BFrWzEGZIAnqoUxC3OIkRWD657g==", - "requires": { - "@vue/runtime-core": "latest", - "@vue/runtime-dom": "latest", - "csstype": "latest", - "lodash-es": "latest" - }, - "dependencies": { - "csstype": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz", - "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==" - } - } - }, - "vue-draggable-next": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/vue-draggable-next/-/vue-draggable-next-2.1.1.tgz", - "integrity": "sha512-f5lmA7t6LMaL4viR7dU30zzvqJzaKQs0ymL0Jy9UDT9uiZ2tXF3MzPzEvpTH2UODXZJkT+SnjeV1fXHMsgXLYA==", - "requires": {} - }, - "vue-eslint-parser": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-8.2.0.tgz", - "integrity": "sha512-hvl8OVT8imlKk/lQyhkshqwQQChzHETcBd5abiO4ePw7ib7QUZLfW+2TUrJHKUvFOCFRJrDin5KJO9OHzB5bRQ==", + "node_modules/vite": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz", + "integrity": "sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==", "dev": true, - "requires": { - "debug": "^4.3.2", - "eslint-scope": "^7.0.0", - "eslint-visitor-keys": "^3.1.0", - "espree": "^9.0.0", - "esquery": "^1.4.0", - "lodash": "^4.17.21", - "semver": "^7.3.5" - }, - "dependencies": { - "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } + "dependencies": { + "esbuild": "^0.18.10", + "postcss": "^8.4.27", + "rollup": "^3.27.1" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@types/node": ">= 14", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } + "terser": { + "optional": true } } }, - "vue-hot-reload-api": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", - "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==", - "dev": true + "node_modules/vite-node": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.34.6.tgz", + "integrity": "sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==", + "dev": true, + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "mlly": "^1.4.0", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0-0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": ">=v14.18.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } }, - "vue-loader": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-17.0.0.tgz", - "integrity": "sha512-OWSXjrzIvbF2LtOUmxT3HYgwwubbfFelN8PAP9R9dwpIkj48TVioHhWWSx7W7fk+iF5cgg3CBJRxwTdtLU4Ecg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "hash-sum": "^2.0.0", - "loader-utils": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } + "node_modules/vitest": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.34.6.tgz", + "integrity": "sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==", + "dev": true, + "dependencies": { + "@types/chai": "^4.3.5", + "@types/chai-subset": "^1.3.3", + "@types/node": "*", + "@vitest/expect": "0.34.6", + "@vitest/runner": "0.34.6", + "@vitest/snapshot": "0.34.6", + "@vitest/spy": "0.34.6", + "@vitest/utils": "0.34.6", + "acorn": "^8.9.0", + "acorn-walk": "^8.2.0", + "cac": "^6.7.14", + "chai": "^4.3.10", + "debug": "^4.3.4", + "local-pkg": "^0.4.3", + "magic-string": "^0.30.1", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "std-env": "^3.3.3", + "strip-literal": "^1.0.1", + "tinybench": "^2.5.0", + "tinypool": "^0.7.0", + "vite": "^3.1.0 || ^4.0.0 || ^5.0.0-0", + "vite-node": "0.34.6", + "why-is-node-running": "^2.2.2" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": ">=v14.18.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@vitest/browser": "*", + "@vitest/ui": "*", + "happy-dom": "*", + "jsdom": "*", + "playwright": "*", + "safaridriver": "*", + "webdriverio": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } + "happy-dom": { + "optional": true }, - "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 + "jsdom": { + "optional": true }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true + "playwright": { + "optional": true }, - "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, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } + "safaridriver": { + "optional": true }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } + "webdriverio": { + "optional": true } } }, - "vue-observe-visibility": { + "node_modules/vue": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.3.4.tgz", + "integrity": "sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==", + "dependencies": { + "@vue/compiler-dom": "3.3.4", + "@vue/compiler-sfc": "3.3.4", + "@vue/runtime-dom": "3.3.4", + "@vue/server-renderer": "3.3.4", + "@vue/shared": "3.3.4" + } + }, + "node_modules/vue-chartjs": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/vue-chartjs/-/vue-chartjs-5.2.0.tgz", + "integrity": "sha512-d3zpKmGZr2OWHQ1xmxBcAn5ShTG917+/UCLaSpaCDDqT0U7DBsvFzTs69ZnHCgKoXT55GZDW8YEj9Av+dlONLA==", + "peerDependencies": { + "chart.js": "^4.1.1", + "vue": "^3.0.0-0 || ^2.7.0" + } + }, + "node_modules/vue-component-type-helpers": { + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-1.8.4.tgz", + "integrity": "sha512-6bnLkn8O0JJyiFSIF0EfCogzeqNXpnjJ0vW/SZzNHfe6sPx30lTtTXlE5TFs2qhJlAtDFybStVNpL73cPe3OMQ==", + "dev": true + }, + "node_modules/vue-draggable-next": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vue-draggable-next/-/vue-draggable-next-2.2.1.tgz", + "integrity": "sha512-EAMS1IRHF0kZO0o5PMOinsQsXIqsrKT1hKmbICxG3UEtn7zLFkLxlAtajcCcUTisNvQ6TtCB5COjD9a1raNADw==", + "peerDependencies": { + "sortablejs": "^1.14.0", + "vue": "^3.2.2" + } + }, + "node_modules/vue-eslint-parser": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.3.1.tgz", + "integrity": "sha512-Clr85iD2XFZ3lJ52/ppmUDG/spxQu6+MAeHXjjyI4I1NUYZ9xmenQp4N0oaHJhrA8OOxltCVxMRfANGa70vU0g==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.6" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/vue-eslint-parser/node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/vue-eslint-parser/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/vue-observe-visibility": { "version": "2.0.0-alpha.1", "resolved": "https://registry.npmjs.org/vue-observe-visibility/-/vue-observe-visibility-2.0.0-alpha.1.tgz", "integrity": "sha512-flFbp/gs9pZniXR6fans8smv1kDScJ8RS7rEpMjhVabiKeq7Qz3D9+eGsypncjfIyyU84saU88XZ0zjbD6Gq/g==", - "requires": {} + "peerDependencies": { + "vue": "^3.0.0" + } }, - "vue-resize": { + "node_modules/vue-resize": { "version": "2.0.0-alpha.1", "resolved": "https://registry.npmjs.org/vue-resize/-/vue-resize-2.0.0-alpha.1.tgz", "integrity": "sha512-7+iqOueLU7uc9NrMfrzbG8hwMqchfVfSzpVlCMeJQe4pyibqyoifDNbKTZvwxZKDvGkB+PdFeKvnGZMoEb8esg==", - "requires": {} + "peerDependencies": { + "vue": "^3.0.0" + } }, - "vue-router": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.1.6.tgz", - "integrity": "sha512-DYWYwsG6xNPmLq/FmZn8Ip+qrhFEzA14EI12MsMgVxvHFDYvlr4NXpVF5hrRH1wVcDP8fGi5F4rxuJSl8/r+EQ==", - "requires": { - "@vue/devtools-api": "^6.4.5" + "node_modules/vue-router": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.2.5.tgz", + "integrity": "sha512-DIUpKcyg4+PTQKfFPX88UWhlagBEBEfJ5A8XDXRJLUnZOvcpMF8o/dnL90vpVkGaPbjvXazV/rC1qBKrZlFugw==", + "dependencies": { + "@vue/devtools-api": "^6.5.0" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.2.0" } }, - "vue-style-loader": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz", - "integrity": "sha512-sFuh0xfbtpRlKfm39ss/ikqs9AbKCoXZBpHeVZ8Tx650o0k0q/YCM7FRvigtxpACezfq6af+a7JeqVTWvncqDg==", + "node_modules/vue-template-compiler": { + "version": "2.7.14", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.14.tgz", + "integrity": "sha512-zyA5Y3ArvVG0NacJDkkzJuPQDF8RFeRlzV2vLeSnhSpieO6LK2OVbdLPi5MPPs09Ii+gMO8nY4S3iKQxBxDmWQ==", "dev": true, - "requires": { - "hash-sum": "^1.0.2", - "loader-utils": "^1.0.2" - }, "dependencies": { - "hash-sum": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", - "dev": true - } + "de-indent": "^1.0.2", + "he": "^1.2.0" } }, - "vue-template-es2015-compiler": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz", - "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", - "dev": true + "node_modules/vue-tsc": { + "version": "1.8.15", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.15.tgz", + "integrity": "sha512-4DoB3LUj7IToLmggoCxRiFG+QU5lem0nv03m1ocqugXA9rSVoTOEoYYaP8vu8b99Eh+/cCVdYOeIAQ+RsgUYUw==", + "dev": true, + "dependencies": { + "@vue/language-core": "1.8.15", + "@vue/typescript": "1.8.15", + "semver": "^7.3.8" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": "*" + } }, - "vue-virtual-scroller": { + "node_modules/vue-virtual-scroller": { "version": "2.0.0-beta.8", "resolved": "https://registry.npmjs.org/vue-virtual-scroller/-/vue-virtual-scroller-2.0.0-beta.8.tgz", "integrity": "sha512-b8/f5NQ5nIEBRTNi6GcPItE4s7kxNHw2AIHLtDp+2QvqdTjVN0FgONwX9cr53jWRgnu+HRLPaWDOR2JPI5MTfQ==", - "requires": { + "dependencies": { "mitt": "^2.1.0", "vue-observe-visibility": "^2.0.0-alpha.1", "vue-resize": "^2.0.0-alpha.1" - } - }, - "vue3-highlightjs": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/vue3-highlightjs/-/vue3-highlightjs-1.0.5.tgz", - "integrity": "sha512-Q4YNPXu0X5VMBnwPVOk+IQf1Ohp9jFdMitEAmzaz8qVVefcQpN6Dx4BnDGKxja3TLDVF+EgL136wC8YzmoCX9w==", - "requires": { - "highlight.js": "^10.3.2" }, - "dependencies": { - "highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==" - } - } - }, - "vuex": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/vuex/-/vuex-4.0.2.tgz", - "integrity": "sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==", - "requires": { - "@vue/devtools-api": "^6.0.0-beta.11" + "peerDependencies": { + "vue": "^3.2.0" } }, - "w3c-xmlserializer": { + "node_modules/w3c-xmlserializer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", "dev": true, - "requires": { + "dependencies": { "xml-name-validator": "^4.0.0" - } - }, - "walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "requires": { - "makeerror": "1.0.12" - } - }, - "watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "requires": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - } - }, - "wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "requires": { - "minimalistic-assert": "^1.0.0" - } - }, - "wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", - "dev": true, - "requires": { - "defaults": "^1.0.3" - } - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", - "dev": true - }, - "webpack": { - "version": "5.82.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.82.1.tgz", - "integrity": "sha512-C6uiGQJ+Gt4RyHXXYt+v9f+SN1v83x68URwgxNQ98cvH8kxiuywWGP4XeNZ1paOzZ63aY3cTciCEQJNFUljlLw==", - "requires": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.14.0", - "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.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.2", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "dependencies": { - "schema-utils": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", - "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" - } - } - }, - "webpack-bundle-analyzer": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz", - "integrity": "sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ==", - "dev": true, - "requires": { - "acorn": "^8.0.4", - "acorn-walk": "^8.0.0", - "chalk": "^4.1.0", - "commander": "^7.2.0", - "gzip-size": "^6.0.0", - "lodash": "^4.17.20", - "opener": "^1.5.2", - "sirv": "^1.0.7", - "ws": "^7.3.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "webpack-chain": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-6.5.1.tgz", - "integrity": "sha512-7doO/SRtLu8q5WM0s7vPKPWX580qhi0/yBHkOxNkv50f6qB76Zy9o2wRTrrPULqYTvQlVHuvbA8v+G5ayuUDsA==", - "dev": true, - "requires": { - "deepmerge": "^1.5.2", - "javascript-stringify": "^2.0.1" }, - "dependencies": { - "deepmerge": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz", - "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==", - "dev": true - } - } - }, - "webpack-dev-middleware": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz", - "integrity": "sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg==", - "dev": true, - "requires": { - "colorette": "^2.0.10", - "memfs": "^3.4.1", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - } - } - } - }, - "webpack-dev-server": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.7.4.tgz", - "integrity": "sha512-nfdsb02Zi2qzkNmgtZjkrMOcXnYZ6FLKcQwpxT7MvmHKc+oTtDsBju8j+NMyAygZ9GW1jMEUpy3itHtqgEhe1A==", - "dev": true, - "requires": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.2.2", - "ansi-html-community": "^0.0.8", - "bonjour": "^3.5.0", - "chokidar": "^3.5.3", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^1.6.0", - "default-gateway": "^6.0.3", - "del": "^6.0.0", - "express": "^4.17.1", - "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", - "http-proxy-middleware": "^2.0.0", - "ipaddr.js": "^2.0.1", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "portfinder": "^1.0.28", - "schema-utils": "^4.0.0", - "selfsigned": "^2.0.0", - "serve-index": "^1.9.1", - "sockjs": "^0.3.21", - "spdy": "^4.0.2", - "strip-ansi": "^7.0.0", - "webpack-dev-middleware": "^5.3.1", - "ws": "^8.4.2" - }, - "dependencies": { - "ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - } - }, - "strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - }, - "ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", - "dev": true, - "requires": {} - } - } - }, - "webpack-merge": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", - "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", - "dev": true, - "requires": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" + "engines": { + "node": ">=14" } }, - "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==" - }, - "webpack-virtual-modules": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.4.3.tgz", - "integrity": "sha512-5NUqC2JquIL2pBAAo/VfBP6KuGkHIZQXW/lNKupLPfhViwh8wNsu0BObtl09yuKZszeEUfbXz8xhrHvSG16Nqw==", - "dev": true - }, - "websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", "dev": true, - "requires": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" + "engines": { + "node": ">=12" } }, - "websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true - }, - "whatwg-encoding": { + "node_modules/whatwg-encoding": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", "dev": true, - "requires": { + "dependencies": { "iconv-lite": "0.6.3" }, - "dependencies": { - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - } + "engines": { + "node": ">=12" } }, - "whatwg-fetch": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", - "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==", - "dev": true - }, - "whatwg-mimetype": { + "node_modules/whatwg-mimetype": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", - "dev": true + "dev": true, + "engines": { + "node": ">=12" + } }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "node_modules/whatwg-url": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-12.0.1.tgz", + "integrity": "sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ==", "dev": true, - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "dependencies": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=14" } }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "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, - "requires": { + "dependencies": { "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, - "which-boxed-primitive": { + "node_modules/which-boxed-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "requires": { + "dev": true, + "dependencies": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", "is-number-object": "^1.0.4", "is-string": "^1.0.5", "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "which-typed-array": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz", - "integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==", - "requires": { + "node_modules/which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dev": true, + "dependencies": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", - "es-abstract": "^1.20.0", "for-each": "^0.3.3", + "gopd": "^1.0.1", "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.9" + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "wildcard": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", - "dev": true + "node_modules/why-is-node-running": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz", + "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==", + "dev": true, + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true + "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, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - } + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/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, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/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, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "wrappy": { + "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, - "write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "node_modules/ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "ws": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", - "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", - "dev": true, - "requires": {} - }, - "xml-name-validator": { + "node_modules/xml-name-validator": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", - "dev": true + "dev": true, + "engines": { + "node": ">=12" + } }, - "xmlchars": { + "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 }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "node_modules/yaml": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.2.tgz", + "integrity": "sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==", "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "engines": { + "node": ">= 14" } }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true - }, - "yocto-queue": { + "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 - }, - "yorkie": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yorkie/-/yorkie-2.0.0.tgz", - "integrity": "sha512-jcKpkthap6x63MB4TxwCyuIGkV0oYP/YRyuQU5UO0Yz/E/ZAu+653/uov+phdmO54n6BcvFRyyt0RRrWdN2mpw==", - "dev": true, - "requires": { - "execa": "^0.8.0", - "is-ci": "^1.0.10", - "normalize-path": "^1.0.0", - "strip-indent": "^2.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "execa": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", - "integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.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" - } - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "normalize-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-1.0.0.tgz", - "integrity": "sha1-MtDkcvkf80VwHBWoMRAY07CpA3k=", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - } + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } } } diff --git a/report-viewer/package.json b/report-viewer/package.json index 1138af4b7..b2810c8fe 100644 --- a/report-viewer/package.json +++ b/report-viewer/package.json @@ -1,64 +1,62 @@ { "name": "report-viewer", - "version": "0.1.0", + "version": "0.0.0", "private": true, "scripts": { - "serve": "vue-cli-service serve", - "dev": "vue-cli-service serve", - "build": "vue-cli-service build", - "lint": "vue-cli-service lint", - "test": "jest" + "dev": "vite --port 8080", + "build": "run-p type-check build-only", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "playwright test", + "build-only": "vite build", + "build-prod": "run-p type-check && vite build --mode prod", + "build-dev": "run-p type-check && vite build --mode dev", + "type-check": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false", + "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore", + "format": "prettier --write src/", + "prepare": "cd .. && husky install report-viewer/.husky" }, "dependencies": { - "@highlightjs/vue-plugin": "^2.1.0", - "chart.js": "^3.9.1", + "@fortawesome/fontawesome-svg-core": "^6.4.2", + "@fortawesome/free-regular-svg-icons": "^6.4.2", + "@fortawesome/free-solid-svg-icons": "^6.4.2", + "@fortawesome/vue-fontawesome": "^3.0.3", + "chart.js": "^4.4.0", "chartjs-plugin-datalabels": "^2.2.0", - "core-js": "^3.29.1", - "gitart-vue-dialog": "^2.4.1", - "highlight.js": "^11.7.0", + "highlight.js": "^11.9.0", "jszip": "^3.10.0", - "node-polyfill-webpack-plugin": "^2.0.0", - "slash": "^5.0.0", - "vue": "^3.2.47", - "vue-chart-3": "^3.1.8", - "vue-draggable-next": "^2.1.1", - "vue-router": "^4.1.6", - "vue-virtual-scroller": "^2.0.0-beta.8", - "vue3-highlightjs": "^1.0.5", - "vuex": "^4.0.2" + "pinia": "^2.1.7", + "slash": "^5.1.0", + "vue": "^3.3.4", + "vue-chartjs": "^5.2.0", + "vue-draggable-next": "^2.2.1", + "vue-router": "^4.2.5", + "vue-virtual-scroller": "^2.0.0-beta.8" }, "devDependencies": { - "@types/jest": "^29.5.0", - "@typescript-eslint/eslint-plugin": "^5.56.0", - "@typescript-eslint/parser": "^5.55.0", - "@vue/cli-plugin-babel": "~5.0.8", - "@vue/cli-plugin-eslint": "~5.0.8", - "@vue/cli-plugin-router": "~5.0.8", - "@vue/cli-plugin-typescript": "~5.0.8", - "@vue/cli-service": "~5.0.8", - "@vue/compiler-sfc": "^3.2.39", - "@vue/eslint-config-prettier": "^7.0.0", - "@vue/eslint-config-typescript": "^10.0.0", - "@vue/test-utils": "^2.3.2", - "@vue/vue3-jest": "^29.2.3", - "eslint": "^8.35.0", - "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-vue": "^8.7.1", - "jest": "^29.5.0", - "jest-environment-jsdom": "^29.5.0", - "jest-transform-stub": "^2.0.0", - "lint-staged": "^13.2.0", - "prettier": "^2.8.6", - "ts-jest": "^29.0.5", - "typescript": "~5.0.2" - }, - "gitHooks": { - "pre-commit": "lint-staged" - }, - "lint-staged": { - "*.{js,jsx,vue,ts,tsx}": [ - "vue-cli-service lint", - "git add" - ] + "@playwright/test": "^1.38.1", + "@rushstack/eslint-patch": "^1.5.1", + "@types/jsdom": "^21.1.3", + "@types/node": "^18.18.6", + "@vitejs/plugin-vue": "^4.4.0", + "@vue/eslint-config-prettier": "^8.0.0", + "@vue/eslint-config-typescript": "^12.0.0", + "@vue/test-utils": "^2.4.1", + "@vue/tsconfig": "^0.4.0", + "autoprefixer": "^10.4.15", + "eslint": "^8.51.0", + "eslint-plugin-vue": "^9.17.0", + "husky": "^8.0.0", + "jsdom": "^22.1.0", + "lint-staged": "^15.0.1", + "npm-run-all": "^4.1.5", + "postcss": "^8.4.31", + "prettier": "^3.0.3", + "prettier-plugin-tailwindcss": "^0.5.6", + "tailwindcss": "^3.3.3", + "typescript": "^5.2.2", + "vite": "^4.5.0", + "vitest": "^0.34.6", + "vue-tsc": "^1.8.15" } } diff --git a/report-viewer/playwright.config.ts b/report-viewer/playwright.config.ts new file mode 100644 index 000000000..e0eebf1a5 --- /dev/null +++ b/report-viewer/playwright.config.ts @@ -0,0 +1,112 @@ +import type { PlaywrightTestConfig } from '@playwright/test' +import { devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +const config: PlaywrightTestConfig = { + testDir: './tests/e2e', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:5173', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'] + } + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'] + } + }, + { + name: 'webkit', + use: { + ...devices['Desktop Safari'] + } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', + port: 5173, + reuseExistingServer: !process.env.CI + } +} + +export default config diff --git a/report-viewer/postcss.config.js b/report-viewer/postcss.config.js new file mode 100644 index 000000000..d62702c9a --- /dev/null +++ b/report-viewer/postcss.config.js @@ -0,0 +1,7 @@ +/* eslint-env node */ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {} + } +} diff --git a/report-viewer/public/404.html b/report-viewer/public/404.html index 5241ba2ca..c53ef5157 100644 --- a/report-viewer/public/404.html +++ b/report-viewer/public/404.html @@ -1,9 +1,9 @@ - - \ No newline at end of file + + diff --git a/report-viewer/public/index.html b/report-viewer/public/index.html deleted file mode 100644 index 9df293f59..000000000 --- a/report-viewer/public/index.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - <%= htmlWebpackPlugin.options.title %> - - - -
- - - diff --git a/report-viewer/sonar-project.properties b/report-viewer/sonar-project.properties new file mode 100644 index 000000000..11d01f4c2 --- /dev/null +++ b/report-viewer/sonar-project.properties @@ -0,0 +1,12 @@ +sonar.projectKey=jplag_report-viewer +sonar.organization=jplag + +# This is the name and version displayed in the SonarCloud UI. +#sonar.projectName=JPlag Plagiarism Detector (Report Viewer) +#sonar.projectVersion=1.0 + +# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. +#sonar.sources=. + +# Encoding of the source code. Default is default system encoding +#sonar.sourceEncoding=UTF-8 \ No newline at end of file diff --git a/report-viewer/src/App.vue b/report-viewer/src/App.vue index c3f51141e..094cf305b 100644 --- a/report-viewer/src/App.vue +++ b/report-viewer/src/App.vue @@ -1,45 +1,31 @@ - - +library.add(faMoon) +library.add(faSun) + diff --git a/report-viewer/src/MaintainabilityTest.md b/report-viewer/src/MaintainabilityTest.md deleted file mode 100644 index 844e12d56..000000000 --- a/report-viewer/src/MaintainabilityTest.md +++ /dev/null @@ -1,11 +0,0 @@ -Testing Maintainability --- -Observing the number of affected artefacts when adding new information to the -report to be displayed. -Adding the number of tokens in a match, which has to be displayed in the MatchesTable in the ComparisonView. -1. Adding int tokens to Match.java [JPlag] -2. Edited convertMatchToReportMatch in ReportObejctFactory to get # token from de.jplag.Match - and save it in Match DTO [JPlag] -3. Added tokens: number to Match.ts [report-viewer] -4. Edited mapMatch in ComparisonFactory.ts to get # tokens from the json file [report-viewer] -5. Edited MatchTable.vue to display the tokens number in the ComparisonView \ No newline at end of file diff --git a/report-viewer/src/assets/double_arrow_black_18dp.svg b/report-viewer/src/assets/double_arrow_black_18dp.svg deleted file mode 100644 index cccc9ab78..000000000 --- a/report-viewer/src/assets/double_arrow_black_18dp.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/report-viewer/src/assets/double_arrow_black_24dp.svg b/report-viewer/src/assets/double_arrow_black_24dp.svg deleted file mode 100644 index fa09e600a..000000000 --- a/report-viewer/src/assets/double_arrow_black_24dp.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/report-viewer/src/assets/help_outline_black_18dp.svg b/report-viewer/src/assets/help_outline_black_18dp.svg deleted file mode 100644 index afa939840..000000000 --- a/report-viewer/src/assets/help_outline_black_18dp.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/report-viewer/src/assets/help_outline_black_24dp.svg b/report-viewer/src/assets/help_outline_black_24dp.svg deleted file mode 100644 index 44e29cdc4..000000000 --- a/report-viewer/src/assets/help_outline_black_24dp.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/report-viewer/src/assets/jplag-dark-transparent.png b/report-viewer/src/assets/jplag-dark-transparent.png new file mode 100644 index 000000000..6ce965f40 Binary files /dev/null and b/report-viewer/src/assets/jplag-dark-transparent.png differ diff --git a/report-viewer/src/assets/jplag-light-transparent.png b/report-viewer/src/assets/jplag-light-transparent.png new file mode 100644 index 000000000..732b433f2 Binary files /dev/null and b/report-viewer/src/assets/jplag-light-transparent.png differ diff --git a/report-viewer/src/assets/keyboard_arrow_down_black_18dp.svg b/report-viewer/src/assets/keyboard_arrow_down_black_18dp.svg deleted file mode 100644 index 192bab9b7..000000000 --- a/report-viewer/src/assets/keyboard_arrow_down_black_18dp.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/report-viewer/src/assets/keyboard_double_arrow_down_black_18dp.svg b/report-viewer/src/assets/keyboard_double_arrow_down_black_18dp.svg deleted file mode 100644 index 757e102e8..000000000 --- a/report-viewer/src/assets/keyboard_double_arrow_down_black_18dp.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/report-viewer/src/assets/keyboard_double_arrow_left_black_18dp.svg b/report-viewer/src/assets/keyboard_double_arrow_left_black_18dp.svg deleted file mode 100644 index 4580fadde..000000000 --- a/report-viewer/src/assets/keyboard_double_arrow_left_black_18dp.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/report-viewer/src/assets/keyboard_double_arrow_left_black_24dp.svg b/report-viewer/src/assets/keyboard_double_arrow_left_black_24dp.svg deleted file mode 100644 index d657b728a..000000000 --- a/report-viewer/src/assets/keyboard_double_arrow_left_black_24dp.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/report-viewer/src/assets/keyboard_double_arrow_up_black_18dp.svg b/report-viewer/src/assets/keyboard_double_arrow_up_black_18dp.svg deleted file mode 100644 index 9f3ad361a..000000000 --- a/report-viewer/src/assets/keyboard_double_arrow_up_black_18dp.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/report-viewer/src/assets/logo-nobg.png b/report-viewer/src/assets/logo-nobg.png deleted file mode 100644 index 5156414b9..000000000 Binary files a/report-viewer/src/assets/logo-nobg.png and /dev/null differ diff --git a/report-viewer/src/assets/radar-chart-configuration.ts b/report-viewer/src/assets/radar-chart-configuration.ts deleted file mode 100644 index baaab388b..000000000 --- a/report-viewer/src/assets/radar-chart-configuration.ts +++ /dev/null @@ -1,22 +0,0 @@ - - const radarChartStyle ={ - fill: true, - backgroundColor: "rgba(149, 168, 241, 0.5)", - borderColor: "rgba(149, 168, 241, 1)", - pointBackgroundColor: "rgba(149, 168, 241, 1)", - pointBorderColor: "#fff", - pointHoverBackgroundColor: "#fff", - pointHoverBorderColor: "rgb(255, 99, 132)", - } - const radarChartOptions = { - legend: { - display: false, - }, - scales: { - r: { - suggestedMin: 50, - suggestedMax: 100, - }, - }, - } - export {radarChartStyle,radarChartOptions} \ No newline at end of file diff --git a/report-viewer/src/components/ButtonComponent.vue b/report-viewer/src/components/ButtonComponent.vue new file mode 100644 index 000000000..4e88de86e --- /dev/null +++ b/report-viewer/src/components/ButtonComponent.vue @@ -0,0 +1,17 @@ + + + + diff --git a/report-viewer/src/components/ClusterRadarChart.vue b/report-viewer/src/components/ClusterRadarChart.vue index e593cccc4..48cd29612 100644 --- a/report-viewer/src/components/ClusterRadarChart.vue +++ b/report-viewer/src/components/ClusterRadarChart.vue @@ -3,125 +3,119 @@ participants in the cluster. --> - +const idOfShownSubmission = ref(selectedOptions.value.length > 0 ? selectedOptions.value[0] : '') - +const radarChartOptions = computed(() => { + return { + legend: { + display: false + }, + scales: { + r: { + suggestedMin: 50, + suggestedMax: 100, + ticks: { + color: graphColors.ticksAndFont.value, + backdropColor: 'rgba(0,0,0,0)' + }, + grid: { + color: graphColors.gridLines.value + }, + angleLines: { + color: graphColors.gridLines.value + } + } + }, + plugins: { + datalabels: { + color: graphColors.ticksAndFont.value + } + } + } +}) + +const chartData: Ref> = computed(() => { + return { + labels: createLabelsFor(idOfShownSubmission.value), + datasets: [ + { + ...radarChartStyle, + label: idOfShownSubmission.value, + data: createDataSetFor(idOfShownSubmission.value) + } + ] + } +}) + +const options = ref(radarChartOptions) + diff --git a/report-viewer/src/components/ClustersList.vue b/report-viewer/src/components/ClustersList.vue deleted file mode 100644 index c56b72f19..000000000 --- a/report-viewer/src/components/ClustersList.vue +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - diff --git a/report-viewer/src/components/CodePanel.vue b/report-viewer/src/components/CodePanel.vue index 3c4ad269b..c057ae5a6 100644 --- a/report-viewer/src/components/CodePanel.vue +++ b/report-viewer/src/components/CodePanel.vue @@ -2,248 +2,131 @@ Panel which displays a submission files with its line of code. --> - + /** + * Language of the file. + */ + highlightLanguage: { + type: String as PropType, + required: true + } +}) - diff --git a/report-viewer/src/components/ComparisonsTable.vue b/report-viewer/src/components/ComparisonsTable.vue index 3b085b5e5..c22f40f70 100644 --- a/report-viewer/src/components/ComparisonsTable.vue +++ b/report-viewer/src/components/ComparisonsTable.vue @@ -2,350 +2,253 @@ Table which display all of the comparisons with their participating ids and similarity percentage for the selected metric. --> - - - diff --git a/report-viewer/src/components/ContainerComponent.vue b/report-viewer/src/components/ContainerComponent.vue new file mode 100644 index 000000000..71cf54fcd --- /dev/null +++ b/report-viewer/src/components/ContainerComponent.vue @@ -0,0 +1,12 @@ + + + + diff --git a/report-viewer/src/components/DistributionDiagram.vue b/report-viewer/src/components/DistributionDiagram.vue index 0eeb70eb7..c6ca774d5 100644 --- a/report-viewer/src/components/DistributionDiagram.vue +++ b/report-viewer/src/components/DistributionDiagram.vue @@ -2,134 +2,125 @@ Bar diagram, displaying the distribution for the selected metric. --> - - - diff --git a/report-viewer/src/components/DropDownSelector.vue b/report-viewer/src/components/DropDownSelector.vue new file mode 100644 index 000000000..1e0946ffd --- /dev/null +++ b/report-viewer/src/components/DropDownSelector.vue @@ -0,0 +1,42 @@ + + + + diff --git a/report-viewer/src/components/ErrorMessage.vue b/report-viewer/src/components/ErrorMessage.vue deleted file mode 100644 index 27036b1a1..000000000 --- a/report-viewer/src/components/ErrorMessage.vue +++ /dev/null @@ -1,26 +0,0 @@ - - - - - \ No newline at end of file diff --git a/report-viewer/src/components/ErrorRouter.vue b/report-viewer/src/components/ErrorRouter.vue deleted file mode 100644 index 7f0b3e4ba..000000000 --- a/report-viewer/src/components/ErrorRouter.vue +++ /dev/null @@ -1,41 +0,0 @@ - - - - - \ No newline at end of file diff --git a/report-viewer/src/components/FilesContainer.vue b/report-viewer/src/components/FilesContainer.vue index 5eae74f34..89862d235 100644 --- a/report-viewer/src/components/FilesContainer.vue +++ b/report-viewer/src/components/FilesContainer.vue @@ -2,131 +2,88 @@ Container containing CodePanels for all of the files in a submission. --> - + /** + * Name of the owner of the files. + */ + fileOwnerDisplayName: { + type: String, + required: true + }, + /** + * Language of the files. + */ + highlightLanguage: { + type: String as PropType, + required: true + } +}) - + +defineExpose({ + scrollTo +}) + diff --git a/report-viewer/src/components/IDsList.vue b/report-viewer/src/components/IDsList.vue deleted file mode 100644 index 31f42cf55..000000000 --- a/report-viewer/src/components/IDsList.vue +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/report-viewer/src/components/InteractableComponent.vue b/report-viewer/src/components/InteractableComponent.vue new file mode 100644 index 000000000..7613cf2d0 --- /dev/null +++ b/report-viewer/src/components/InteractableComponent.vue @@ -0,0 +1,14 @@ + + + + diff --git a/report-viewer/src/components/LineOfCode.vue b/report-viewer/src/components/LineOfCode.vue deleted file mode 100644 index eb530102c..000000000 --- a/report-viewer/src/components/LineOfCode.vue +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/report-viewer/src/components/LoadingCircle.vue b/report-viewer/src/components/LoadingCircle.vue new file mode 100644 index 000000000..e94062a97 --- /dev/null +++ b/report-viewer/src/components/LoadingCircle.vue @@ -0,0 +1,18 @@ + + + diff --git a/report-viewer/src/components/MatchList.vue b/report-viewer/src/components/MatchList.vue new file mode 100644 index 000000000..17e5bee28 --- /dev/null +++ b/report-viewer/src/components/MatchList.vue @@ -0,0 +1,61 @@ + + + + diff --git a/report-viewer/src/components/MatchTable.vue b/report-viewer/src/components/MatchTable.vue deleted file mode 100644 index ecfbec114..000000000 --- a/report-viewer/src/components/MatchTable.vue +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - diff --git a/report-viewer/src/components/MetricButton.vue b/report-viewer/src/components/MetricButton.vue deleted file mode 100644 index 76c46e545..000000000 --- a/report-viewer/src/components/MetricButton.vue +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - diff --git a/report-viewer/src/components/ScrollableComponent.vue b/report-viewer/src/components/ScrollableComponent.vue new file mode 100644 index 000000000..69ae30b86 --- /dev/null +++ b/report-viewer/src/components/ScrollableComponent.vue @@ -0,0 +1,10 @@ + + diff --git a/report-viewer/src/components/SearchBarComponent.vue b/report-viewer/src/components/SearchBarComponent.vue new file mode 100644 index 000000000..1c9b315f5 --- /dev/null +++ b/report-viewer/src/components/SearchBarComponent.vue @@ -0,0 +1,44 @@ + + + + diff --git a/report-viewer/src/components/TextInformation.vue b/report-viewer/src/components/TextInformation.vue index 342bb1ac9..e9e54640c 100644 --- a/report-viewer/src/components/TextInformation.vue +++ b/report-viewer/src/components/TextInformation.vue @@ -1,145 +1,32 @@ - - - \ No newline at end of file diff --git a/report-viewer/src/components/ToolTipComponent.vue b/report-viewer/src/components/ToolTipComponent.vue new file mode 100644 index 000000000..48212c0f5 --- /dev/null +++ b/report-viewer/src/components/ToolTipComponent.vue @@ -0,0 +1,73 @@ + + + diff --git a/report-viewer/src/components/VersionInfoComponent.vue b/report-viewer/src/components/VersionInfoComponent.vue new file mode 100644 index 000000000..0d056d077 --- /dev/null +++ b/report-viewer/src/components/VersionInfoComponent.vue @@ -0,0 +1,49 @@ + + + diff --git a/report-viewer/src/components/optionsSelectors/MetricSelector.vue b/report-viewer/src/components/optionsSelectors/MetricSelector.vue new file mode 100644 index 000000000..22f3a4bbb --- /dev/null +++ b/report-viewer/src/components/optionsSelectors/MetricSelector.vue @@ -0,0 +1,41 @@ + + + diff --git a/report-viewer/src/components/optionsSelectors/OptionComponent.vue b/report-viewer/src/components/optionsSelectors/OptionComponent.vue new file mode 100644 index 000000000..443940a84 --- /dev/null +++ b/report-viewer/src/components/optionsSelectors/OptionComponent.vue @@ -0,0 +1,27 @@ + + + diff --git a/report-viewer/src/components/optionsSelectors/OptionsSelectorComponent.vue b/report-viewer/src/components/optionsSelectors/OptionsSelectorComponent.vue new file mode 100644 index 000000000..94397decd --- /dev/null +++ b/report-viewer/src/components/optionsSelectors/OptionsSelectorComponent.vue @@ -0,0 +1,76 @@ + + + + diff --git a/report-viewer/src/main.ts b/report-viewer/src/main.ts index b67d365b9..97759edbf 100644 --- a/report-viewer/src/main.ts +++ b/report-viewer/src/main.ts @@ -1,12 +1,19 @@ -import {createApp} from "vue"; -import App from "./App.vue"; -import router from "./router"; -import store from "./store/store" -import VueVirtualScroller from "vue-virtual-scroller" -import 'highlight.js/styles/vs.css' -import 'gitart-vue-dialog/dist/style.css' -import 'highlight.js/lib/common'; -import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'; - - -createApp(App).use(router).use(store).use(VueVirtualScroller).mount("#app"); +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import { router } from './router' +import VueVirtualScroller from 'vue-virtual-scroller' +import 'highlight.js/lib/common' + +import 'vue-virtual-scroller/dist/vue-virtual-scroller.css' + +import './style.css' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) +app.use(VueVirtualScroller) + +app.mount('#app') diff --git a/report-viewer/src/model/Cluster.ts b/report-viewer/src/model/Cluster.ts index 77e297a0a..da042df6a 100644 --- a/report-viewer/src/model/Cluster.ts +++ b/report-viewer/src/model/Cluster.ts @@ -1,5 +1,12 @@ +/** + * Represents a cluster identified by the clustering algorithm. + * A cluster is a group of similar submissions. + * @property averageSimilarity - The average similarity of the submissions in the cluster. + * @property strength - The strength of the cluster + * @property members - The ids of the submissions in the cluster + */ export type Cluster = { - averageSimilarity: number, - strength: number, - members: Array -} \ No newline at end of file + averageSimilarity: number + strength: number + members: Array +} diff --git a/report-viewer/src/model/ClusterListElement.ts b/report-viewer/src/model/ClusterListElement.ts index 1b36f58b9..8a4339430 100644 --- a/report-viewer/src/model/ClusterListElement.ts +++ b/report-viewer/src/model/ClusterListElement.ts @@ -1,10 +1,16 @@ +/** + * Stores the identified clusters, with information about the matches between the submissions. + * @property averageSimilarity - The average similarity of the submissions in the cluster. + * @property strength - The strength of the cluster + * @property members - The ids of the submissions in the cluster, and the matches between them + */ type ClusterListElement = { - averageSimilarity: number; - strength: number; - members: ClusterListElementMember; -}; -type ClusterListElementMember = Map< - string, - Array<{ matchedWith: string; percentage: number }> ->; -export { ClusterListElement, ClusterListElementMember }; + averageSimilarity: number + strength: number + members: ClusterListElementMember +} +/** + * The ids of the submissions in the cluster, and the matches between them + */ +type ClusterListElementMember = Map> +export type { ClusterListElement, ClusterListElementMember } diff --git a/report-viewer/src/model/Comparison.ts b/report-viewer/src/model/Comparison.ts index 1007dc847..6fafbc60f 100644 --- a/report-viewer/src/model/Comparison.ts +++ b/report-viewer/src/model/Comparison.ts @@ -1,100 +1,102 @@ -import { Match } from "./Match"; -import { SubmissionFile } from "./SubmissionFile"; -import { MatchInSingleFile } from "./MatchInSingleFile"; +import type { Match } from './Match' +import type { SubmissionFile } from '@/stores/state' +import { MatchInSingleFile } from './MatchInSingleFile' +import type { MetricType } from './MetricType' /** * Comparison model used by the ComparisonView */ export class Comparison { - private readonly _firstSubmissionId: string; - private readonly _secondSubmissionId: string; - private readonly _similarity: number; + private readonly _firstSubmissionId: string + private readonly _secondSubmissionId: string + private readonly _similarities: Record + private _filesOfFirstSubmission: SubmissionFile[] + private _filesOfSecondSubmission: SubmissionFile[] + private _allMatches: Array constructor( firstSubmissionId: string, secondSubmissionId: string, - similarity: number + similarities: Record, + filesOfFirstSubmission: SubmissionFile[], + filesOfSecondSubmission: SubmissionFile[], + allMatches: Array ) { - this._firstSubmissionId = firstSubmissionId; - this._secondSubmissionId = secondSubmissionId; - this._similarity = similarity; - this._filesOfFirstSubmission = new Map(); - this._filesOfSecondSubmission = new Map(); - this._colors = []; - this._allMatches = []; - this._matchesInFirstSubmission = new Map(); - this._matchesInSecondSubmissions = new Map(); + this._firstSubmissionId = firstSubmissionId + this._secondSubmissionId = secondSubmissionId + this._similarities = similarities + this._filesOfFirstSubmission = filesOfFirstSubmission + this._filesOfSecondSubmission = filesOfSecondSubmission + this._allMatches = allMatches } - private _filesOfFirstSubmission: Map; - - get filesOfFirstSubmission(): Map { - return this._filesOfFirstSubmission; - } - - set filesOfFirstSubmission(value: Map) { - this._filesOfFirstSubmission = value; - } - - private _filesOfSecondSubmission: Map; - - get filesOfSecondSubmission(): Map { - return this._filesOfSecondSubmission; - } - - set filesOfSecondSubmission(value: Map) { - this._filesOfSecondSubmission = value; - } - - private _colors: Array; - - get colors(): Array { - return this._colors; + /** + * @return Map of all files of the first submission + */ + get filesOfFirstSubmission(): SubmissionFile[] { + return this._filesOfFirstSubmission } - set colors(value: Array) { - this._colors = value; + /** + * @return Map of all files of the second submission + */ + get filesOfSecondSubmission(): SubmissionFile[] { + return this._filesOfSecondSubmission } - private _allMatches: Array; - + /** + * @return Array of all matches + */ get allMatches(): Array { - return this._allMatches; + return this._allMatches } - set allMatches(value: Array) { - this._allMatches = value; - } - - private _matchesInFirstSubmission: Map>; - + /** + * @return Map of all matches in the first submission + */ get matchesInFirstSubmission(): Map> { - return this._matchesInFirstSubmission; + return this.groupMatchesByFileName(1) } - set matchesInFirstSubmission(value: Map>) { - this._matchesInFirstSubmission = value; - } - - private _matchesInSecondSubmissions: Map>; - + /** + * @return Map of all matches in the second submission + */ get matchesInSecondSubmissions(): Map> { - return this._matchesInSecondSubmissions; + return this.groupMatchesByFileName(2) } - set matchesInSecondSubmissions(value: Map>) { - this._matchesInSecondSubmissions = value; + /** + * @return Id of the first submission + */ + get firstSubmissionId() { + return this._firstSubmissionId } - get firstSubmissionId(): string { - return this._firstSubmissionId; + /** + * @return Id of the second submission + */ + get secondSubmissionId() { + return this._secondSubmissionId } - get secondSubmissionId(): string { - return this._secondSubmissionId; + /** + * @return Similarity of the two submissions + */ + get similarities() { + return this._similarities } - get similarity(): number { - return this._similarity; + private groupMatchesByFileName(index: 1 | 2): Map> { + const acc = new Map>() + this._allMatches.forEach((val) => { + const name = index === 1 ? (val.firstFile as string) : (val.secondFile as string) + + if (!acc.get(name)) { + acc.set(name, []) + } + + acc.get(name)?.push(new MatchInSingleFile(val, index)) + }) + return acc } } diff --git a/report-viewer/src/model/ComparisonListElement.ts b/report-viewer/src/model/ComparisonListElement.ts index e3ca29778..c4eacebc0 100644 --- a/report-viewer/src/model/ComparisonListElement.ts +++ b/report-viewer/src/model/ComparisonListElement.ts @@ -1,10 +1,19 @@ +import type { MetricType } from './MetricType' + /** * Comparison model used by the Comparison Table in Overview. Only the needed attributes to display are included. * For full comparison model see Comparison.ts + * @see Comparison + * @property sortingPlace - Where the comparison is placed in the list sorted by the current metric + * @property id - Index of the comparison in the sorted and filtered list + * @property firstSubmissionId - Id of the first submission + * @property secondSubmissionId - Id of the second submission + * @property similarity - Similarity of the two submissions */ export type ComparisonListElement = { - id: number, - firstSubmissionId: string, - secondSubmissionId: string, - similarity: number -} \ No newline at end of file + sortingPlace: number + id: number + firstSubmissionId: string + secondSubmissionId: string + similarities: Record +} diff --git a/report-viewer/src/model/Distribution.ts b/report-viewer/src/model/Distribution.ts new file mode 100644 index 000000000..00da64d22 --- /dev/null +++ b/report-viewer/src/model/Distribution.ts @@ -0,0 +1,12 @@ +export abstract class Distribution { + protected readonly _distribution: number[] + + constructor(distribution: number[]) { + this._distribution = distribution + } + + /** + * Returns the distribution summed at every tenth percentile + */ + public abstract splitIntoTenBuckets(): number[] +} diff --git a/report-viewer/src/model/HundredValueDistribution.ts b/report-viewer/src/model/HundredValueDistribution.ts new file mode 100644 index 000000000..91c2831d1 --- /dev/null +++ b/report-viewer/src/model/HundredValueDistribution.ts @@ -0,0 +1,22 @@ +import { Distribution } from './Distribution' + +/** + * This class represents he JPlag Distribution of a metric. + * It is composed of 100 values, each representing the sum of the values of the metric in the corresponding percentile. + */ +export class HundredValueDistribution extends Distribution { + constructor(distribution: number[]) { + super(distribution) + } + + /** + * Returns the distribution summed at every tenth percentile + */ + public splitIntoTenBuckets(): number[] { + const tenValueArray = new Array(10).fill(0) + for (let i = 99; i >= 0; i--) { + tenValueArray[Math.floor(i / 10)] += this._distribution[i] + } + return tenValueArray + } +} diff --git a/report-viewer/src/model/Language.ts b/report-viewer/src/model/Language.ts new file mode 100644 index 000000000..a9b9b91f8 --- /dev/null +++ b/report-viewer/src/model/Language.ts @@ -0,0 +1,101 @@ +/** + * Enum for the language parsers JPlag supports + */ +enum ParserLanguage { + JAVA = 'Javac based AST plugin', + PYTHON = 'Python3 Parser', + CPP = 'C/C++ Scanner [basic markup]', + CPP2 = 'C/C++ Parser', + C_SHARP = 'C# 6 Parser', + EMF_METAMODEL_DYNAMIC = 'emf-dynamic', + EMF_METAMODEL = 'EMF metamodel', + EMF_MODEL = 'EMF models (dynamically created token set)', + GO = 'Go Parser', + KOTLIN = 'Kotlin Parser', + R_LANG = 'R Parser', + RUST = 'Rust Language Module', + SCALA = 'Scala parser', + SCHEME = 'SchemeR4RS Parser [basic markup]', + SWIFT = 'Swift Parser', + TEXT = 'Text Parser (naive)', + SCXML = 'SCXML (Statechart XML)', + LLVM = 'LLVMIR Parser' +} + +/** + * Gets the LanguageParser enum value for the given language + * @param language String representation of language the files were parsed with + * @returns The LanguageParser enum value + */ +function getLanguageParser(language: string): ParserLanguage { + for (const key in ParserLanguage) { + if (ParserLanguage[key as keyof typeof ParserLanguage] === language) { + return ParserLanguage[key as keyof typeof ParserLanguage] + } + } + + throw new Error(`Language ${language} not found`) +} + +/** + * Enum for the highlight.js languages + * The strings are the names of the languages in highlight.js (https://github.com/highlightjs/highlight.js/blob/main/SUPPORTED_LANGUAGES.md) + */ +enum HighlightLanguage { + JAVA = 'java', + PYTHON = 'python', + CPP = 'cpp', + C_SHARP = 'csharp', + XML = 'xml', + GO = 'go', + KOTLIN = 'kotlin', + R_LANG = 'r', + RUST = 'rust', + SCALA = 'scala', + SCHEME = 'scheme', + SWIFT = 'swift', + TEXT = 'text' +} + +/** + * Gets the highlight.js language for the given language + * @param language Language the files were parsed with + * @returns The language for highlight.js + */ +function getHighlightLanguage(language: ParserLanguage | undefined): HighlightLanguage { + switch (language) { + case ParserLanguage.PYTHON: + return HighlightLanguage.PYTHON + case ParserLanguage.CPP: + case ParserLanguage.CPP2: + return HighlightLanguage.CPP + case ParserLanguage.C_SHARP: + return HighlightLanguage.C_SHARP + case ParserLanguage.EMF_METAMODEL: + case ParserLanguage.EMF_METAMODEL_DYNAMIC: + case ParserLanguage.EMF_MODEL: + case ParserLanguage.SCXML: + return HighlightLanguage.XML + case ParserLanguage.GO: + return HighlightLanguage.GO + case ParserLanguage.KOTLIN: + return HighlightLanguage.KOTLIN + case ParserLanguage.R_LANG: + return HighlightLanguage.R_LANG + case ParserLanguage.RUST: + return HighlightLanguage.RUST + case ParserLanguage.SCALA: + return HighlightLanguage.SCALA + case ParserLanguage.SCHEME: + return HighlightLanguage.SCHEME + case ParserLanguage.SWIFT: + return HighlightLanguage.SWIFT + case ParserLanguage.TEXT: + return HighlightLanguage.TEXT + case ParserLanguage.JAVA: + default: + return HighlightLanguage.JAVA + } +} + +export { ParserLanguage, getLanguageParser, HighlightLanguage, getHighlightLanguage } diff --git a/report-viewer/src/model/Match.ts b/report-viewer/src/model/Match.ts index 86be0d3b4..43df6d1e2 100644 --- a/report-viewer/src/model/Match.ts +++ b/report-viewer/src/model/Match.ts @@ -1,13 +1,21 @@ /** * Match between two files of two submissions. + * @property firstFile - Path to the file of the first submission. + * @property secondFile - Path to the file of the second submission. + * @property startInFirst - Starting line of the match in the first file. + * @property endInFirst - Ending line of the match in the first file. + * @property startInSecond - Starting line of the match in the second file. + * @property endInSecond - Ending line of the match in the second file. + * @property tokens - Number of tokens in the match. + * @property color - Color of the match. */ export type Match = { - firstFile: string, - secondFile: string, - startInFirst: number, - endInFirst: number, - startInSecond: number, - endInSecond: number, - tokens: number, - color: string -} \ No newline at end of file + firstFile: string + secondFile: string + startInFirst: number + endInFirst: number + startInSecond: number + endInSecond: number + tokens: number + color: string +} diff --git a/report-viewer/src/model/MatchInSingleFile.ts b/report-viewer/src/model/MatchInSingleFile.ts index dc95b2c19..bcaae43c0 100644 --- a/report-viewer/src/model/MatchInSingleFile.ts +++ b/report-viewer/src/model/MatchInSingleFile.ts @@ -1,20 +1,43 @@ +import type { Match } from './Match' + /** * Describes a match in a single file. */ -export type MatchInSingleFile = { - start: number, - end: number, - /** - * The files container containing the file of the second submission to which this is matched. - */ - linked_panel: number, - /** - * The file name containing the same match in the second submission. - */ - linked_file: string, - /** - * The start of the match in the second file. - */ - linked_line: number, - color: string -} \ No newline at end of file +export class MatchInSingleFile { + private readonly _match: Match + private readonly _index: 1 | 2 + + constructor(match: Match, index: 1 | 2) { + this._match = match + this._index = index + } + + /** + * The match object. + */ + get match(): Match { + return this._match + } + + /** + * The start line of the match. + */ + get start(): number { + if (this._index === 1) { + return this._match.startInFirst + } else { + return this._match.startInSecond + } + } + + /** + * The end line of the match. + */ + get end(): number { + if (this._index === 1) { + return this._match.endInFirst + } else { + return this._match.endInSecond + } + } +} diff --git a/report-viewer/src/model/Metric.ts b/report-viewer/src/model/Metric.ts deleted file mode 100644 index 97e80452b..000000000 --- a/report-viewer/src/model/Metric.ts +++ /dev/null @@ -1,12 +0,0 @@ -import {ComparisonListElement} from "./ComparisonListElement"; - -/** - * Metric used in the Jplag Comparison - */ -export type Metric = { - metricName: string, - description: string, - metricThreshold: number, - distribution: Array, - comparisons: Array -} \ No newline at end of file diff --git a/report-viewer/src/model/MetricType.ts b/report-viewer/src/model/MetricType.ts new file mode 100644 index 000000000..08c81d072 --- /dev/null +++ b/report-viewer/src/model/MetricType.ts @@ -0,0 +1,28 @@ +/** + * This enum maps the metric type to the index they have in the generated JSON and respectivly in the store. + */ +export enum MetricType { + AVERAGE = 'AVG', + MAXIMUM = 'MAX' +} + +type MetricToolTipData = { + longName: string + shortName: string + tooltip: string +} + +export const metricToolTips: Record = { + [MetricType.AVERAGE]: { + longName: 'Average Similarity', + shortName: 'AVG', + tooltip: + 'The average similarity of the two files.\nA high similarity indicates that the programms work in a similar way.' + }, + [MetricType.MAXIMUM]: { + longName: 'Maximum Similarity', + shortName: 'MAX', + tooltip: + 'The maximum similarity of the two files.\nUsefull if programms are very dfferent in size.' + } +} diff --git a/report-viewer/src/model/Overview.ts b/report-viewer/src/model/Overview.ts index 98984164a..63b705dde 100644 --- a/report-viewer/src/model/Overview.ts +++ b/report-viewer/src/model/Overview.ts @@ -1,86 +1,122 @@ -import { Metric } from "./Metric"; -import { Cluster } from "@/model/Cluster"; +import type { Distribution } from './Distribution' +import type { Cluster } from '@/model/Cluster' +import type { ComparisonListElement } from './ComparisonListElement' +import type { MetricType } from './MetricType' +import type { ParserLanguage } from './Language' +/** + * Model of the Overview file generated by JPlag + */ export class Overview { - private readonly _submissionFolderPath: Array; - private readonly _baseCodeFolderPath: string; - private readonly _language: string; - private readonly _fileExtensions: Array; - private readonly _matchSensitivity: number; - private readonly _submissionIdsToComparisonFileName: Map>; - private readonly _dateOfExecution: string; - private readonly _durationOfExecution: number; - private readonly _metrics: Array; - private readonly _clusters: Array; - private readonly _totalComparisons: number; + private readonly _submissionFolderPath: Array + private readonly _baseCodeFolderPath: string + private readonly _language: ParserLanguage + private readonly _fileExtensions: Array + private readonly _matchSensitivity: number + private readonly _dateOfExecution: string + private readonly _durationOfExecution: number + private readonly _topComparisons: Array + private readonly _distributions: Record + private readonly _clusters: Array + private readonly _totalComparisons: number constructor( submissionFolderPath: Array, baseCodeFolderPath: string, - language: string, + language: ParserLanguage, fileExtensions: Array, matchSensitivity: number, dateOfExecution: string, durationOfExecution: number, - metrics: Array, + topComparisons: Array, + distributions: Record, clusters: Array, - totalComparisons: number, - submissionIdsToComparisonFileName: Map> + totalComparisons: number ) { - this._submissionFolderPath = submissionFolderPath; - this._baseCodeFolderPath = baseCodeFolderPath; - this._language = language; - this._fileExtensions = fileExtensions; - this._matchSensitivity = matchSensitivity; - this._dateOfExecution = dateOfExecution; - this._durationOfExecution = durationOfExecution; - this._metrics = metrics; - this._clusters = clusters; - this. _submissionIdsToComparisonFileName = submissionIdsToComparisonFileName; - this._totalComparisons= totalComparisons; - } - get submissionIdsToComparisonFileName(): Map> { - return this.submissionIdsToComparisonFileName; + this._submissionFolderPath = submissionFolderPath + this._baseCodeFolderPath = baseCodeFolderPath + this._language = language + this._fileExtensions = fileExtensions + this._matchSensitivity = matchSensitivity + this._dateOfExecution = dateOfExecution + this._durationOfExecution = durationOfExecution + this._topComparisons = topComparisons + this._distributions = distributions + this._clusters = clusters + this._totalComparisons = totalComparisons } - get submissionFolderPath(): Array { - return this._submissionFolderPath; + /** + * @return Path to the folder containing the submissions + */ + get submissionFolderPath() { + return this._submissionFolderPath } - get baseCodeFolderPath(): string { - return this._baseCodeFolderPath; + /** + * @return Path to the folder containing the base code + */ + get baseCodeFolderPath() { + return this._baseCodeFolderPath } - get language(): string { - return this._language; + /** + * @return Language of the submissions + */ + get language() { + return this._language } - get fileExtensions(): Array { - return this._fileExtensions; + /** + * @return File extensions of the submissions + */ + get fileExtensions() { + return this._fileExtensions } - get matchSensitivity(): number { - return this._matchSensitivity; + /** + * @return Match sensitivity used for running JPlag + */ + get matchSensitivity() { + return this._matchSensitivity } + /** + * @return Date of execution of JPlag + */ + get dateOfExecution() { + return this._dateOfExecution + } - get dateOfExecution(): string { - return this._dateOfExecution; + /** + * @return Time JPlag took to run + */ + get durationOfExecution() { + return this._durationOfExecution } - get durationOfExecution(): number { - return this._durationOfExecution; + get topComparisons() { + return this._topComparisons } - get metrics(): Array { - return this._metrics; + /** + * @return Distributions used in the JPlag Comparison + */ + get distribution() { + return this._distributions } - get clusters(): Array { - return this._clusters; + /** + * @return Clusters of the JPlag Comparison + */ + get clusters() { + return this._clusters } - get totalComparisons(): number { - return this._totalComparisons; + /** + * @return Total number of comparisons + */ + get totalComparisons() { + return this._totalComparisons } } diff --git a/report-viewer/src/model/SubmissionFile.ts b/report-viewer/src/model/SubmissionFile.ts deleted file mode 100644 index b9cf43a46..000000000 --- a/report-viewer/src/model/SubmissionFile.ts +++ /dev/null @@ -1,10 +0,0 @@ -export type SubmissionFile = { - /** - * Code lines of the file. - */ - lines: Array; - /** - * Indicates whether the file is displayed or not. - */ - collapsed: boolean; -} \ No newline at end of file diff --git a/report-viewer/src/model/TenValueDistribution.ts b/report-viewer/src/model/TenValueDistribution.ts new file mode 100644 index 000000000..d4264f360 --- /dev/null +++ b/report-viewer/src/model/TenValueDistribution.ts @@ -0,0 +1,16 @@ +import { Distribution } from './Distribution' + +/** + * This class represents he JPlag Distribution of a metric. + * It is composed of 10 values, each representing the sum of the values of the metric in the corresponding percentiles. + */ +/** @deprecated since 5.0.0. Use the new format with {@link HundredValueDistribution} */ +export class TenValueDistribution extends Distribution { + constructor(distribution: number[]) { + super(distribution) + } + + public splitIntoTenBuckets(): number[] { + return this._distribution + } +} diff --git a/report-viewer/src/model/Version.ts b/report-viewer/src/model/Version.ts index 5d796f7a6..fa194b45d 100644 --- a/report-viewer/src/model/Version.ts +++ b/report-viewer/src/model/Version.ts @@ -1,5 +1,36 @@ -export type Version = { - major: number, - minor: number, - patch: number -} \ No newline at end of file +/** + * Version of the report viewer. + */ +export class Version { + private major: number + private minor: number + private patch: number + + constructor(major: number, minor: number, patch: number) { + this.major = major + this.minor = minor + this.patch = patch + } + + public toString(): string { + return this.major + '.' + this.minor + '.' + this.patch + } + + public compareTo(other: Version): number { + if (this.major !== other.major) { + return this.major - other.major + } + if (this.minor !== other.minor) { + return this.minor - other.minor + } + return this.patch - other.patch + } + + public isDevVersion(): boolean { + return this.major === 0 && this.minor === 0 && this.patch === 0 + } + + public isInvalid(): boolean { + return this.major < 0 || this.minor < 0 || this.patch < 0 + } +} diff --git a/report-viewer/src/model/factories/BaseFactory.ts b/report-viewer/src/model/factories/BaseFactory.ts new file mode 100644 index 000000000..ec7fe0dcd --- /dev/null +++ b/report-viewer/src/model/factories/BaseFactory.ts @@ -0,0 +1,56 @@ +import { store } from '@/stores/store' +import { ZipFileHandler } from '@/utils/fileHandling/ZipFileHandler' + +/** + * This class provides some basic functionality for the factories. + */ +export class BaseFactory { + /** + * Returns the content of a file through the stored loading type. + * @param path - Path to the file + * @return Content of the file + * @throws Error if the file could not be found + */ + protected static async getFile(path: string): Promise { + if (store().state.localModeUsed) { + if (store().state.zipModeUsed) { + await new ZipFileHandler().handleFile(await this.getLocalFile('results.zip')) + return this.getFileFromStore(path) + } else { + return await (await this.getLocalFile(`/files/${path}`)).text() + } + } else if (store().state.zipModeUsed) { + return this.getFileFromStore(path) + } else if (store().state.singleModeUsed) { + return store().state.singleFillRawContent + } + throw new Error('No loading type specified') + } + + private static getFileFromStore(path: string): string { + const index = Object.keys(store().state.files).find((name) => name.endsWith(path)) + if (index == undefined) { + throw new Error(`Could not find ${path} in zip file.`) + } + const file = store().state.files[index] + if (file == undefined) { + throw new Error(`Could not load ${path}.`) + } + return file + } + + /** + * Returns the content of a file from the local files. + * @param path - Path to the file + * @return Content of the file + * @throws Error if the file could not be found + */ + protected static async getLocalFile(path: string): Promise { + const request = await fetch(window.location.origin + '/' + path) + if (request.status == 200) { + return request.blob() + } else { + throw new Error(`Could not find ${path} in local files.`) + } + } +} diff --git a/report-viewer/src/model/factories/ComparisonFactory.ts b/report-viewer/src/model/factories/ComparisonFactory.ts index 90353d326..355e2c795 100644 --- a/report-viewer/src/model/factories/ComparisonFactory.ts +++ b/report-viewer/src/model/factories/ComparisonFactory.ts @@ -1,140 +1,116 @@ -import { Comparison } from "../Comparison"; -import { Match } from "../Match"; -import { SubmissionFile } from "../SubmissionFile"; -import { MatchInSingleFile } from "../MatchInSingleFile"; -import store from "@/store/store"; - -export class ComparisonFactory { - static getComparison(json: Record): Comparison { - const filesOfFirstSubmission = store.getters.filesOfSubmission( - json.id1 - ); - const filesOfSecondSubmission = store.getters.filesOfSubmission( - json.id2 - ); - - const filesOfFirstConverted = this.convertToFilesByName( - filesOfFirstSubmission - ); - const filesOfSecondConverted = this.convertToFilesByName( - filesOfSecondSubmission - ); - - const matches = json.matches as Array>; - - - const colors = this.generateColorsForMatches(matches.length); - const coloredMatches = matches.map((match, index) => - this.mapMatch(match, colors[index]) - ); - - const matchesInFirst = this.groupMatchesByFileName(coloredMatches, 1); - const matchesInSecond = this.groupMatchesByFileName(coloredMatches, 2); - - const comparison = new Comparison( - json.id1 as string, - json.id2 as string, - json.similarity as number - ); - comparison.filesOfFirstSubmission = filesOfFirstConverted; - comparison.filesOfSecondSubmission = filesOfSecondConverted; - comparison.colors = colors; - comparison.allMatches = coloredMatches; - comparison.matchesInFirstSubmission = matchesInFirst; - comparison.matchesInSecondSubmissions = matchesInSecond; +import { Comparison } from '../Comparison' +import type { Match } from '../Match' +import { store } from '@/stores/store' +import { generateColors } from '@/utils/ColorUtils' +import slash from 'slash' +import { BaseFactory } from './BaseFactory' +import { MetricType } from '../MetricType' + +/** + * Factory class for creating Comparison objects + */ +export class ComparisonFactory extends BaseFactory { + public static async getComparison(id1: string, id2: string): Promise { + const filePath = store().getComparisonFileName(id1, id2) + if (!filePath) { + throw new Error('Comparison file not specified') + } - return comparison; + return await this.extractComparison(JSON.parse(await this.getFile(filePath))) } - private static convertToFilesByName( - files: Array<{ name: string; value: string }> - ): Map { - const map = new Map(); - files.forEach((val) => { - if (!map.get(val.name)) { - map.set(val.name as string, { - lines: [], - collapsed: false, - }); - } - map.set(val.name as string, { - lines: val.value.split(/\r?\n/), - collapsed: false, - }); - }); - return map; + /** + * Creates a comparison object from a json object created by by JPlag + * @param json the json object + */ + private static async extractComparison(json: Record): Promise { + const firstSubmissionId = json.id1 as string + const secondSubmissionId = json.id2 as string + if (store().state.localModeUsed && !store().state.zipModeUsed) { + await this.loadSubmissionFilesFromLocal(firstSubmissionId) + await this.loadSubmissionFilesFromLocal(secondSubmissionId) + } + const filesOfFirstSubmission = store().filesOfSubmission(firstSubmissionId) + const filesOfSecondSubmission = store().filesOfSubmission(secondSubmissionId) + + const matches = json.matches as Array> + + const matchSaturation = 0.8 + const matchLightness = 0.5 + const matchAlpha = 0.3 + const colors = generateColors(matches.length, matchSaturation, matchLightness, matchAlpha) + const coloredMatches = matches.map((match, index) => this.mapMatch(match, colors[index])) + + return new Comparison( + firstSubmissionId, + secondSubmissionId, + this.extractSimilarities(json), + filesOfFirstSubmission, + filesOfSecondSubmission, + coloredMatches + ) } - private static groupMatchesByFileName( - matches: Array, - index: number - ): Map> { - const acc = new Map>(); - matches.forEach((val) => { - const name = - index === 1 ? (val.firstFile as string) : (val.secondFile as string); - - if (!acc.get(name)) { - acc.set(name, []); - } + private static extractSimilarities(json: Record): Record { + if (json.similarities) { + return this.extractSimilaritiesFromMap(json.similarities as Record) + } else if (json.similarity) { + return this.extractSimilaritiesFromSingleValue(json.similarity as number) + } + throw new Error('No similarities found in comparison file') + } - if (index === 1) { - const newVal: MatchInSingleFile = { - start: val.startInFirst as number, - end: val.endInFirst as number, - linked_panel: 2, - linked_file: val.secondFile as string, - linked_line: val.startInSecond as number, - color: val.color as string, - }; - acc.get(name)?.push(newVal); - } else { - const newVal: MatchInSingleFile = { - start: val.startInSecond as number, - end: val.endInSecond as number, - linked_panel: 1, - linked_file: val.firstFile as string, - linked_line: val.startInFirst as number, - color: val.color as string, - }; - acc.get(name)?.push(newVal); - } - }); - return acc; + /** @deprecated since 5.0.0. Use the new format with {@link extractSimilaritiesFromMap} */ + private static extractSimilaritiesFromSingleValue( + avgSimilarity: number + ): Record { + return { + [MetricType.AVERAGE]: avgSimilarity, + [MetricType.MAXIMUM]: Number.NaN + } } + private static extractSimilaritiesFromMap( + similarityMap: Record + ): Record { + const similarities = {} as Record + for (const [key, value] of Object.entries(similarityMap)) { + similarities[key as MetricType] = value + } + return similarities + } - private static generateColorsForMatches(num: number): Array { - const colors: Array = []; - const numberOfColorsInFirstInterval = Math.round((80 - 20) / ((80 - 20) + (340 - 160)) * num); // number of colors from the first interval - const numberOfColorsInSecondInterval = num - numberOfColorsInFirstInterval; // number of colors from the second interval - ComparisonFactory.generateColorsForInterval(20, 80, numberOfColorsInFirstInterval, colors); - ComparisonFactory.generateColorsForInterval(160, 340, numberOfColorsInSecondInterval, colors); - return colors; + private static async getSubmissionFileListFromLocal(submissionId: string): Promise { + return JSON.parse( + await this.getLocalFile(`files/submissionFileIndex.json`).then((file) => file.text()) + ).submission_file_indexes[submissionId].map((file: string) => slash(file)) } - private static generateColorsForInterval(intervalStart: number, intervalEnd: number, numberOfColorsInInterval: number, colors: Array){ - const interval = intervalEnd - intervalStart; - const hueDelta = Math.trunc(interval / numberOfColorsInInterval); - for (let i = 0; i < numberOfColorsInInterval; i++) { - const hue = intervalStart + i * hueDelta; - colors.push(`hsla(${hue}, 80%, 50%, 0.3)`); + private static async loadSubmissionFilesFromLocal(submissionId: string) { + try { + const fileList = await this.getSubmissionFileListFromLocal(submissionId) + for (const filePath of fileList) { + store().saveSubmissionFile({ + fileName: slash(filePath), + submissionId: submissionId, + data: await this.getLocalFile(`files/files/${filePath}`).then((file) => file.text()) + }) + } + } catch (e) { + console.log(e) } } - private static mapMatch( - match: Record, - color: string - ): Match { + private static mapMatch(match: Record, color: string): Match { return { - firstFile: match.file1 as string, - secondFile: match.file2 as string, + firstFile: slash(match.file1 as string), + secondFile: slash(match.file2 as string), startInFirst: match.start1 as number, endInFirst: match.end1 as number, startInSecond: match.start2 as number, endInSecond: match.end2 as number, tokens: match.tokens as number, - color: color, - }; + color: color + } } } diff --git a/report-viewer/src/model/factories/OverviewFactory.ts b/report-viewer/src/model/factories/OverviewFactory.ts index bae450d06..1a4b772e9 100644 --- a/report-viewer/src/model/factories/OverviewFactory.ts +++ b/report-viewer/src/model/factories/OverviewFactory.ts @@ -1,74 +1,54 @@ -import { Overview } from "../Overview"; -import { Metric } from "../Metric"; -import { ComparisonListElement } from "../ComparisonListElement"; -import { Cluster } from "@/model/Cluster"; -import store from "@/store/store"; -import { Version } from "../Version"; -import versionJson from "../../version.json"; - -export class OverviewFactory { - - static reportViewerVersion: Version = versionJson["report_viewer_version"] !== undefined ? versionJson["report_viewer_version"] : {major: -1, minor: -1, patch: -1}; - - static getOverview(json: Record): Overview { - const versionField = json.jplag_version as Record; - const jplagVersion: Version = { - major: versionField.major, - minor: versionField.minor, - patch: versionField.patch - } +import { Overview } from '../Overview' +import type { ComparisonListElement } from '../ComparisonListElement' +import type { Cluster } from '@/model/Cluster' +import { store } from '@/stores/store' +import { Version } from '../Version' +import versionJson from '@/version.json' +import { getLanguageParser } from '../Language' +import { Distribution } from '../Distribution' +import { MetricType } from '../MetricType' +import { BaseFactory } from './BaseFactory' +import { HundredValueDistribution } from '../HundredValueDistribution' +import { TenValueDistribution } from '../TenValueDistribution' + +/** + * Factory class for creating Overview objects + */ +export class OverviewFactory extends BaseFactory { + static reportViewerVersion: Version = + versionJson['report_viewer_version'] !== undefined + ? this.extractVersion(versionJson['report_viewer_version'] as Record) + : new Version(-1, -1, -1) + + /** + * Gets the overview file based on the used mode (zip, local, single). + */ + public static async getOverview(): Promise { + return this.extractOverview(JSON.parse(await this.getFile('overview.json'))) + } + + /** + * Creates an overview object from a json object created by by JPlag + * @param json the json object + */ + private static extractOverview(json: Record): Overview { + const versionField = json.jplag_version as Record + const jplagVersion = this.extractVersion(versionField) + + OverviewFactory.compareVersions(jplagVersion, this.reportViewerVersion) + + const submissionFolder = json.submission_folder_path as Array + const baseCodeFolder = json.base_code_folder_path as string + const language = getLanguageParser(json.language as string) + const fileExtensions = json.file_extensions as Array + const matchSensitivity = json.match_sensitivity as number + const dateOfExecution = json.date_of_execution as string + const duration = json.execution_time as number as number + const totalComparisons = json.total_comparisons as number + + this.saveIdToDisplayNameMap(json) + this.saveComparisonFilesLookup(json) - OverviewFactory.compareVersions(jplagVersion, this.reportViewerVersion); - - const submissionFolder = json.submission_folder_path as Array; - const baseCodeFolder = ""; - const language = json.language as string; - const fileExtensions = json.file_extensions as Array; - const matchSensitivity = json.match_sensitivity as number; - const jsonSubmissions = json.submission_id_to_display_name as Map; - const map = new Map(Object.entries(jsonSubmissions)); - const dateOfExecution = json.date_of_execution as string; - const duration = json.execution_time as number as number; - const metrics = [] as Array; - const clusters = [] as Array; - const totalComparisons= json.total_comparisons as number; - (json.metrics as Array).forEach((jsonMetric) => { - const metric = jsonMetric as Record; - const comparisons = [] as Array; - - (metric.topComparisons as Array>).forEach( - (jsonComparison,index) => { - const comparison: ComparisonListElement = { - id: index + 1 as number, - firstSubmissionId: jsonComparison.first_submission as string, - secondSubmissionId: jsonComparison.second_submission as string, - similarity: jsonComparison.similarity as number, - }; - comparisons.push(comparison); - } - ); - metrics.push({ - metricName: metric.name as string, - metricThreshold: metric.threshold as number, - distribution: metric.distribution as Array, - comparisons: comparisons, - description: metric.description as string, - }); - }); - store.commit("saveSubmissionNames", map); - if (json.clusters) { - (json.clusters as Array).forEach((jsonCluster) => { - const cluster = jsonCluster as Record; - const newCluster: Cluster = { - averageSimilarity: cluster.average_similarity as number, - strength: cluster.strength as number, - members: cluster.members as Array, - }; - clusters.push(newCluster); - }); - } - - OverviewFactory.saveSubmissionsToComparisonNameMap(json); return new Overview( submissionFolder, baseCodeFolder, @@ -77,51 +57,175 @@ export class OverviewFactory { matchSensitivity, dateOfExecution, duration, - metrics, - clusters, - totalComparisons, - new Map() - ); + this.extractTopComparisons(json), + this.extractDistributions(json), + this.extractClusters(json), + totalComparisons + ) } - static compareVersions(jsonVersion: Version, reportViewerVersion: Version) { - if(sessionStorage.getItem("versionAlert")===null) { + public static extractVersion(versionField: Record): Version { + return new Version(versionField.major, versionField.minor, versionField.patch) + } - if (reportViewerVersion.major === 0 && reportViewerVersion.minor === 0 && reportViewerVersion.patch === 0) { - alert("The development version (0.0.0) of JPlag is used."); - } + private static extractDistributions( + json: Record + ): Record { + if (json.distributions) { + return this.extractDistributionsFromMap(json.distributions as Record>) + } else if (json.metrics) { + return this.extractDistributionsFromMetrics(json.metrics as Array>) + } + throw new Error('No distributions found') + } - if (jsonVersion.major !== reportViewerVersion.major || - jsonVersion.minor !== reportViewerVersion.minor || - jsonVersion.patch !== reportViewerVersion.patch) { - if(reportViewerVersion.major === -1 && reportViewerVersion.minor === -1 && reportViewerVersion.patch === -1){ - console.warn("The report viewer's version cannot be read from version.json file. Please configure it correctly."); - } else { - console.warn("The result's version tag does not fit the report viewer's version. Trying to read it anyhow but be careful."); - alert("The result's version(" + jsonVersion.major + "." + jsonVersion.minor + "." + jsonVersion.patch + ") tag does not fit the report viewer's version(" + reportViewerVersion.major + "." + reportViewerVersion.minor + "." + reportViewerVersion.patch + "). " + - "Trying to read it anyhow but be careful.") + private static extractDistributionsFromMap( + distributionsMap: Record> + ): Record { + const distributions = {} as Record + for (const [key, value] of Object.entries(distributionsMap)) { + distributions[key as MetricType] = new HundredValueDistribution(value as Array) + } + return distributions + } + + /** @deprecated since 5.0.0. Use the new format with {@link extractDistributionsFromMap} */ + private static extractDistributionsFromMetrics( + metrics: Array> + ): Record { + return { + [MetricType.AVERAGE]: new TenValueDistribution(metrics[0].distribution as Array), + [MetricType.MAXIMUM]: new TenValueDistribution(metrics[1].distribution as Array) + } + } + + private static extractTopComparisons( + json: Record + ): Array { + if (json.top_comparisons) { + return this.extractTopComparisonsFromMap( + json.top_comparisons as Array> + ) + } else if (json.metrics) { + return this.extractTopComparisonsFromMetrics(json.metrics as Array>) + } + throw new Error('No top comparisons found') + } + + private static extractTopComparisonsFromMap(jsonComparisons: Array>) { + const comparisons = [] as Array + let counter = 0 + for (const topComparison of jsonComparisons) { + comparisons.push({ + sortingPlace: counter++, + id: counter, + firstSubmissionId: topComparison.first_submission as string, + secondSubmissionId: topComparison.second_submission as string, + similarities: topComparison.similarities as Record + }) + } + return comparisons + } + + /** @deprecated since 5.0.0. Use the new format with {@link extractTopComparisonsFromMap} */ + private static extractTopComparisonsFromMetrics(metrics: Array>) { + const averageSimilarities: Map = new Map() + const comparisons = [] as Array + + // Save the average similarities in a temporary map to combine them with the max similarities later + for (const comparison of metrics[0].topComparisons as Array>) { + averageSimilarities.set( + (comparison.first_submission as string) + '-' + (comparison.second_submission as string), + comparison.similarity as number + ) + } + + // Extract the max similarities and combine them with the average similarities + let counter = 0 + for (const comparison of metrics[1].topComparisons as Array>) { + const avg = averageSimilarities.get( + (comparison.first_submission as string) + '-' + (comparison.second_submission as string) + ) + comparisons.push({ + sortingPlace: counter++, + id: counter, + firstSubmissionId: comparison.first_submission as string, + secondSubmissionId: comparison.second_submission as string, + similarities: { + [MetricType.AVERAGE]: avg as number, + [MetricType.MAXIMUM]: comparison.similarity as number } - } + }) + } + + return comparisons + } + + private static extractClusters(json: Record): Array { + if (!json.clusters) { + return [] + } - sessionStorage.setItem("versionAlert","true"); + const clusters = [] as Array + for (const jsonCluster of json.clusters as Array>) { + clusters.push({ + averageSimilarity: jsonCluster.average_similarity as number, + strength: jsonCluster.strength as number, + members: jsonCluster.members as Array + }) } + return clusters + } + + private static saveIdToDisplayNameMap(json: Record) { + const jsonSubmissions = json.submission_id_to_display_name as Map + const map = new Map(Object.entries(jsonSubmissions)) + + store().saveSubmissionNames(map) } - private static saveSubmissionsToComparisonNameMap(json: Record){ - const submissionIdsToComparisonName = - json.submission_ids_to_comparison_file_name as Map< + private static saveComparisonFilesLookup(json: Record) { + const submissionIdsToComparisonName = json.submission_ids_to_comparison_file_name as Map< string, Map - >; - const test: Array> = Object.entries( - submissionIdsToComparisonName - ); - const comparisonMap = new Map>( - ); - for (const [key, value] of test) { - comparisonMap.set(key as string, new Map(Object.entries(value as object))); + > + const test: Array> = Object.entries(submissionIdsToComparisonName) + const comparisonMap = new Map>() + for (const [key, value] of test) { + comparisonMap.set(key as string, new Map(Object.entries(value as object))) + } + + store().saveComparisonFileLookup(comparisonMap) } - store.commit("saveComparisonFileLookup", comparisonMap); + /** + * Compares the two versions and shows an alert if they are not equal and puts out a warning if they are not + * @param jsonVersion the version of the json file + * @param reportViewerVersion the version of the report viewer + */ + static compareVersions(jsonVersion: Version, reportViewerVersion: Version) { + if (sessionStorage.getItem('versionAlert') === null) { + if (jsonVersion.compareTo(reportViewerVersion) !== 0) { + if (reportViewerVersion.isInvalid()) { + console.warn( + "The report viewer's version cannot be read from version.json file. Please configure it correctly." + ) + } else { + console.warn( + "The result's version tag does not fit the report viewer's version. Trying to read it anyhow but be careful." + ) + alert( + "The result's version(" + + jsonVersion.toString() + + ") tag does not fit the report viewer's version(" + + reportViewerVersion.toString() + + '). ' + + 'Trying to read it anyhow but be careful.' + ) + } + } + + sessionStorage.setItem('versionAlert', 'true') + } } } diff --git a/report-viewer/src/router/index.ts b/report-viewer/src/router/index.ts index 212a0241f..31283c13d 100644 --- a/report-viewer/src/router/index.ts +++ b/report-viewer/src/router/index.ts @@ -1,36 +1,50 @@ -import "./public-path" -import {createRouter, createWebHistory, RouteRecordRaw} from "vue-router"; +import { createRouter, createWebHistory } from 'vue-router' +import FileUploadView from '@/views/FileUploadView.vue' +import OverviewViewWrapper from '@/viewWrapper/OverviewViewWrapper.vue' +import ComparisonViewWrapper from '@/viewWrapper/ComparisonViewWrapper.vue' +import ErrorView from '@/views/ErrorView.vue' +import InformationViewWrapper from '@/viewWrapper/InformationViewWrapper.vue' +import ClusterViewWrapper from '@/viewWrapper/ClusterViewWrapper.vue' /** - * Router containing the navigation destinations. + * The router is used to navigate between the different views of the application. */ -const routes: Array = [ - { - path: "/", - name: "FileUploadView", - component: () => import('@/views/FileUploadView.vue'), - }, - { - path: "/overview", - name: "OverviewView", - component: () => import('@/views/OverviewView.vue'), - }, - { - path: "/comparison/:firstId/:secondId", - name: "ComparisonView", - component: () => import('@/views/ComparisonView.vue'), - props: true, - }, - { - path: "/error", - name: "ErrorView", - component: () => import('@/views/ErrorView.vue'), - }, -]; - const router = createRouter({ - history: createWebHistory(__webpack_public_path__), - routes, -}); + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'FileUploadView', + component: FileUploadView + }, + { + path: '/overview', + name: 'OverviewView', + component: OverviewViewWrapper + }, + { + path: '/comparison/:firstId/:secondId', + name: 'ComparisonView', + component: ComparisonViewWrapper, + props: true + }, + { + path: '/error', + name: 'ErrorView', + component: ErrorView + }, + { + path: '/cluster/:clusterIndex', + name: 'ClusterView', + component: ClusterViewWrapper, + props: true + }, + { + path: '/info', + name: 'InfoView', + component: InformationViewWrapper + } + ] +}) -export default router; +export { router } diff --git a/report-viewer/src/router/public-path.js b/report-viewer/src/router/public-path.js deleted file mode 100644 index 9330b3135..000000000 --- a/report-viewer/src/router/public-path.js +++ /dev/null @@ -1,4 +0,0 @@ -/* global __webpack_public_path__:writable */ -/* exported __webpack_public_path__ */ - -__webpack_public_path__ = window.PUBLIC_PATH; \ No newline at end of file diff --git a/report-viewer/src/shims-vue.d.ts b/report-viewer/src/shims-vue.d.ts deleted file mode 100644 index 3804a43e2..000000000 --- a/report-viewer/src/shims-vue.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -/* eslint-disable */ -declare module '*.vue' { - import type { DefineComponent } from 'vue' - const component: DefineComponent<{}, {}, any> - export default component -} diff --git a/report-viewer/src/store/store.ts b/report-viewer/src/store/store.ts deleted file mode 100644 index 58486d51d..000000000 --- a/report-viewer/src/store/store.ts +++ /dev/null @@ -1,172 +0,0 @@ -import { createStore } from "vuex"; - -/** - * Local store. Stores the state of the application. - */ - -interface State { - /** - * The set of ids to be hidden. - */ - anonymous: Set; - /** - * Stored files if zip mode is used. Stores the files as key - file name, value - file string - */ - files: Record; - submissions: Record>; - /** - * Indicates whether local mode is used. - */ - local: boolean; - /** - * Indicates whether zip mode is used. - */ - zip: boolean; - /** - * Indicates whether single file mode is used. - */ - single: boolean; - /** - * Files string if single mode is used. - */ - fileString: string; - - fileIdToDisplayName: Map; - submissionIdsToComparisonFileName: Map>; -} - -interface File { - fileName: string; - data: string; -} -interface SubmissionFile { - name: string; - file: File; -} - -interface LoadConfiguration { - local: boolean; - zip: boolean; - single: boolean; - fileString: string; -} - -const store = createStore({ - state: { - submissionIdsToComparisonFileName: new Map>(), - /** - * The set of ids to be hidden. - */ - anonymous: new Set(), - /** - * Stored files if zip mode is used. Stores the files as key - file name, value - file string - */ - files: {}, - submissions: {}, - /** - * Indicates whether local mode is used. - */ - local: false, - /** - * Indicates whether zip mode is used. - */ - zip: false, - /** - * Indicates whether single file mode is used. - */ - single: false, - /** - * Files string if single mode is used. - */ - fileString: "", - fileIdToDisplayName: new Map(), - }, - getters: { - filesOfSubmission: (state) => (name: string) => { - return Array.from(state.submissions[name], ([name, value]) => ({ - name, - value, - })); - }, - submissionDisplayName: (state) => (id: string) => { - return state.fileIdToDisplayName.get(id); - }, - getSubmissionIds(state): Array { - return Array.from(state.fileIdToDisplayName.keys()); - }, - getComparisonFileName: - (state) => (submissionId1: string, submissionId2: string) => { - return state.submissionIdsToComparisonFileName - .get(submissionId1) - ?.get(submissionId2); - }, - getComparisonFileForSubmissions: - (state, getters) => (submissionId1: string, submissionId2: string) => { - const expectedFileName = getters.getComparisonFileName( - submissionId1, - submissionId2 - ); - const index = Object.keys(store.state.files).find((name) => - name.endsWith(expectedFileName) - ); - return index != undefined ? store.state.files[index] : undefined; - }, - }, - mutations: { - clearStore(){ - store.replaceState({ - submissionIdsToComparisonFileName: new Map>(), - anonymous: new Set(), - files: {}, - submissions: {}, - local: false, - zip: false, - single: false, - fileString: "", - fileIdToDisplayName: new Map(), - }); - }, - addAnonymous(state: State, id) { - for (let i = 0; i < id.length; i++) { - state.anonymous.add(id[i]); - } - }, - saveComparisonFileLookup( - state: State, - map: Map> - ) { - state.submissionIdsToComparisonFileName = map; - }, - removeAnonymous(state, id) { - for (let i = 0; i < id.length; i++) { - state.anonymous.delete(id[i]); - } - }, - resetAnonymous(state) { - state.anonymous = new Set(); - }, - saveFile(state, file: File) { - state.files[file.fileName] = file.data; - }, - saveSubmissionNames(state, names: Map) { - state.fileIdToDisplayName = names; - }, - saveSubmissionFile(state, submissionFile: SubmissionFile) { - if (!state.submissions[submissionFile.name]) { - state.submissions[submissionFile.name] = new Map(); - } - state.submissions[submissionFile.name].set( - submissionFile.file.fileName, - submissionFile.file.data - ); - }, - setLoadingType(state, payload: LoadConfiguration) { - state.local = payload.local; - state.zip = payload.zip; - state.single = payload.single; - state.fileString = payload.fileString; - }, - }, -}); - -export default store; diff --git a/report-viewer/src/stores/state.ts b/report-viewer/src/stores/state.ts new file mode 100644 index 000000000..9eb9d80db --- /dev/null +++ b/report-viewer/src/stores/state.ts @@ -0,0 +1,82 @@ +import type { MetricType } from '@/model/MetricType' + +/** + * Local store. Stores the state of the application. + */ +export interface State { + /** + * The set of ids to be hidden. + */ + anonymous: Set + /** + * Stored files if zip mode is used. Stores the files as key - file name, value - file string + */ + files: Record + submissions: Record> + /** + * Indicates whether local mode is used. + */ + localModeUsed: boolean + /** + * Indicates whether zip mode is used. + */ + zipModeUsed: boolean + /** + * Indicates whether single file mode is used. + */ + singleModeUsed: boolean + /** + * Files string if single mode is used. + */ + singleFillRawContent: string + + fileIdToDisplayName: Map + submissionIdsToComparisonFileName: Map> +} + +/** + * Internal representation of a single file. + */ +export interface File { + /** + * The name of the file. + */ + fileName: string + /** + * The files content. + */ + data: string +} + +/** + * Internal representation of a single file from a submission. + */ +export interface SubmissionFile extends File { + /** + * The id of the submission. + */ + submissionId: string +} + +/** + * Load configuration is used to indicate which mode is used. + */ +export interface LoadConfiguration { + local: boolean + zip: boolean + single: boolean +} + +export interface UIState { + useDarkMode: boolean + comparisonTableSortingMetric: MetricType + distributionChartConfig: DistributionChartConfig +} + +/** + * Configuration for the distribution chart. + */ +export interface DistributionChartConfig { + metric: MetricType + xScale: 'linear' | 'logarithmic' +} diff --git a/report-viewer/src/stores/store.ts b/report-viewer/src/stores/store.ts new file mode 100644 index 000000000..08f2ad702 --- /dev/null +++ b/report-viewer/src/stores/store.ts @@ -0,0 +1,182 @@ +import { defineStore } from 'pinia' +import type { State, SubmissionFile, File, LoadConfiguration, UIState } from './state' +import { MetricType } from '@/model/MetricType' + +/** + * The store is a global state management system. It is used to store the state of the application. + */ +const store = defineStore('store', { + state: (): { state: State; uiState: UIState } => ({ + state: { + submissionIdsToComparisonFileName: new Map>(), + anonymous: new Set(), + files: {}, + submissions: {}, + // Mode that was used to load the files + localModeUsed: false, + zipModeUsed: false, + singleModeUsed: false, + // only used in single mode + singleFillRawContent: '', + fileIdToDisplayName: new Map() + }, + uiState: { + useDarkMode: false, + comparisonTableSortingMetric: MetricType.AVERAGE, + distributionChartConfig: { + metric: MetricType.AVERAGE, + xScale: 'linear' + } + } + }), + getters: { + /** + * @param submissionID the name of the submission + * @returns files in the submission of the given name + */ + filesOfSubmission: + (state) => + (submissionId: string): SubmissionFile[] => { + return Array.from(state.state.submissions[submissionId], ([name, value]) => ({ + submissionId, + fileName: name, + data: value + })) + }, + /** + * @param name the name of the submission + * @returns the display name of the submission + */ + submissionDisplayName: (state) => (id: string) => { + return state.state.fileIdToDisplayName.get(id) + }, + /** + * @returns the Ids of all submissions + */ + getSubmissionIds(state): Array { + return Array.from(state.state.fileIdToDisplayName.keys()) + }, + /** + * @param submissionId1 the id of the first submission + * @param submissionId2 the id of the second submission + * @returns the name of the comparison file between the two submissions + */ + getComparisonFileName: (state) => (submissionId1: string, submissionId2: string) => { + return state.state.submissionIdsToComparisonFileName.get(submissionId1)?.get(submissionId2) + }, + /** + * @param submissionId1 the id of the first submission + * @param submissionId2 the id of the second submission + * @returns the comparison file between the two submissions + */ + getComparisonFileForSubmissions() { + return (submissionId1: string, submissionId2: string) => { + const expectedFileName = this.getComparisonFileName(submissionId1, submissionId2) + const index = expectedFileName + ? Object.keys(this.state.files).find((name) => name.endsWith(expectedFileName)) + : undefined + return index != undefined ? this.state.files[index] : undefined + } + } + }, + actions: { + /** + * Clears the store + */ + clearStore() { + this.state = { + submissionIdsToComparisonFileName: new Map>(), + anonymous: new Set(), + files: {}, + submissions: {}, + localModeUsed: false, + zipModeUsed: false, + singleModeUsed: false, + singleFillRawContent: '', + fileIdToDisplayName: new Map() + } + }, + /** + * Adds the given ids to the set of anonymous submissions + * @param id the id of the submission to hide + */ + addAnonymous(id: string[]) { + for (let i = 0; i < id.length; i++) { + this.state.anonymous.add(id[i]) + } + }, + /** + * Removes the given ids from the set of anonymous submissions + * @param id the id of the submission to show + */ + removeAnonymous(id: string[]) { + for (let i = 0; i < id.length; i++) { + this.state.anonymous.delete(id[i]) + } + }, + /** + * Clears the set of anonymous submissions + */ + resetAnonymous() { + this.state.anonymous = new Set() + }, + /** + * Sets the map of submission ids to comparison file names + * @param map the map to set + */ + saveComparisonFileLookup(map: Map>) { + this.state.submissionIdsToComparisonFileName = map + }, + /** + * Saves the given file + * @param file the file to save + */ + saveFile(file: File) { + this.state.files[file.fileName] = file.data + }, + /** + * Saves the given submission names + * @param names the names to save + */ + saveSubmissionNames(names: Map) { + this.state.fileIdToDisplayName = names + }, + /** + * Saves the given submission file + * @param submissionFile the file to save + */ + saveSubmissionFile(submissionFile: SubmissionFile) { + if (!this.state.submissions[submissionFile.submissionId]) { + this.state.submissions[submissionFile.submissionId] = new Map() + } + this.state.submissions[submissionFile.submissionId].set( + submissionFile.fileName, + submissionFile.data + ) + }, + /** + * Sets the loading type + * @param payload Type used to input JPlag results + */ + setLoadingType(payload: LoadConfiguration) { + this.state.localModeUsed = payload.local + this.state.zipModeUsed = payload.zip + this.state.singleModeUsed = payload.single + }, + /** + * Sets the raw content of the single file mode + * @param payload Raw content of the single file mode + */ + setSingleFileRawContent(payload: string) { + this.state.singleFillRawContent = payload + }, + /** + * Switches whether darkMode is being used for the UI + */ + changeUseDarkMode() { + this.uiState.useDarkMode = !this.uiState.useDarkMode + } + } +}) + +export { store } diff --git a/report-viewer/src/style.css b/report-viewer/src/style.css new file mode 100644 index 000000000..3bf327dfa --- /dev/null +++ b/report-viewer/src/style.css @@ -0,0 +1,31 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + #app { + font-family: Avenir, Helvetica, Arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + } + + h2 { + @apply text-3xl; + } + + *::-webkit-scrollbar { + @apply h-[6px] w-[6px] cursor-pointer; + } + *::-webkit-scrollbar-track { + @apply rounded-full border-2 bg-scrollbar-backgorund-light dark:bg-scrollbar-backgorund-dark; + } + *::-webkit-scrollbar-thumb { + @apply rounded-full border-2 bg-scrollbar-thumb-light dark:bg-scrollbar-thumb-dark; + } +} + +@layer components { + .break-anywhere { + overflow-wrap: anywhere; + } +} diff --git a/report-viewer/src/utils/CodeHighlighter.ts b/report-viewer/src/utils/CodeHighlighter.ts new file mode 100644 index 000000000..6c1d19e85 --- /dev/null +++ b/report-viewer/src/utils/CodeHighlighter.ts @@ -0,0 +1,32 @@ +import type { HighlightLanguage } from '@/model/Language' +import hljs from 'highlight.js' + +/** + * Hightlights the given code with the given language. + * Splits the resulting html into seperate lines. + * The returned string is an array of html lines, consisting of spans with the hljs classes and the code. + * Source: https://stackoverflow.com/a/70656181 + * @param code Code to highlight + * @param lang Language to highlight the code with + * @returns + */ +export function highlight(code: string, lang: HighlightLanguage) { + const highlightedCode = hljs.highlight(code, { language: lang.valueOf() }).value + const openTags: string[] = [] + const formatedCode = highlightedCode + .replace(/(]*>)|(<\/span>)|(\n)/g, (match: string) => { + if (match === '\n') { + return ''.repeat(openTags.length) + '\n' + openTags.join('') + } + + if (match === '') { + openTags.pop() + } else { + openTags.push(match) + } + + return match + }) + .split('\n') + return formatedCode +} diff --git a/report-viewer/src/utils/ColorUtils.ts b/report-viewer/src/utils/ColorUtils.ts new file mode 100644 index 000000000..e44adec27 --- /dev/null +++ b/report-viewer/src/utils/ColorUtils.ts @@ -0,0 +1,74 @@ +import { store } from '@/stores/store' +import { computed } from 'vue' + +/** + * Generates an array of HSL-Colors + * @param numberOfColors Number of colors to generate + * @param saturation Saturation of the colors [0,1] + * @param lightness Lightness of the colors [0,1] + * @param alpha Alpha value of the colors [0,1] + */ +function generateColors( + numberOfColors: number, + saturation: number, + lightness: number, + alpha: number +) { + const numberOfColorsInFirstInterval = Math.round( + ((80 - 20) / (80 - 20 + (340 - 160))) * numberOfColors + ) // number of colors from the first interval + const numberOfColorsInSecondInterval = numberOfColors - numberOfColorsInFirstInterval // number of colors from the second interval + + const colors: Array = generateColorsForInterval( + 20, + 80, + numberOfColorsInFirstInterval, + saturation, + lightness, + alpha + ) + colors.push(...generateColorsForInterval(160, 340, numberOfColorsInSecondInterval, 0.8, 0.5, 0.3)) + return colors +} + +/** + * Genertes an array of HSL-Colors for a given interval + * @param intervalStart start of the interval [0,360] + * @param intervalEnd end of the interval [0,360] and > intervalStart + * @param numberOfColorsInInterval Number of colors to generate in the interval + * @param saturation [0,1] + * @param lightness [0,1] + * @param alpha [0,1] + * @returns Array of strings in format 'hsla(hue, saturation, lightness, alpha)' + */ +function generateColorsForInterval( + intervalStart: number, + intervalEnd: number, + numberOfColorsInInterval: number, + saturation: number, + lightness: number, + alpha: number +) { + const colors: Array = [] + const interval = intervalEnd - intervalStart + const hueDelta = Math.trunc(interval / numberOfColorsInInterval) + for (let i = 0; i < numberOfColorsInInterval; i++) { + const hue = intervalStart + i * hueDelta + colors.push(`hsla(${hue}, ${saturation * 100}%, ${lightness * 100}%, ${alpha})`) + } + return colors +} + +const graphColors = { + ticksAndFont: computed(() => { + return store().uiState.useDarkMode ? '#ffffff' : '#000000' + }), + gridLines: computed(() => { + return store().uiState.useDarkMode ? 'rgba(256, 256, 256, 0.2)' : 'rgba(0, 0, 0, 0.2)' + }), + contentFill: 'rgba(190, 22, 34, 0.5)', + contentBorder: 'rgb(127, 15, 24)', + pointFill: 'rgba(190, 22, 34, 1)' +} + +export { generateColors, graphColors } diff --git a/report-viewer/src/utils/Utils.ts b/report-viewer/src/utils/ComparisonUtils.ts similarity index 82% rename from report-viewer/src/utils/Utils.ts rename to report-viewer/src/utils/ComparisonUtils.ts index 42de74611..6dde383d2 100644 --- a/report-viewer/src/utils/Utils.ts +++ b/report-viewer/src/utils/ComparisonUtils.ts @@ -5,5 +5,5 @@ * @param line Line number. */ export function generateLineCodeLink(index: number, fileName: string, line: number): string { - return String(index).concat(fileName).concat(String(line)) + return String(index).concat(fileName).concat(String(line)) } diff --git a/report-viewer/src/utils/fileHandling/FileHandler.ts b/report-viewer/src/utils/fileHandling/FileHandler.ts new file mode 100644 index 000000000..bd55ed100 --- /dev/null +++ b/report-viewer/src/utils/fileHandling/FileHandler.ts @@ -0,0 +1,10 @@ +/** + * Abstract base class for handling files. + */ +export abstract class FileHandler { + /** + * Loads the content of the given file and stores it in the store. + * @param file File to handle + */ + public abstract handleFile(file: Blob): Promise +} diff --git a/report-viewer/src/utils/fileHandling/JsonFileHandler.ts b/report-viewer/src/utils/fileHandling/JsonFileHandler.ts new file mode 100644 index 000000000..1d3dce180 --- /dev/null +++ b/report-viewer/src/utils/fileHandling/JsonFileHandler.ts @@ -0,0 +1,23 @@ +import { store } from '@/stores/store' +import { FileHandler } from './FileHandler' + +/** + * Class for handling single json files. + */ +export class JsonFileHandler extends FileHandler { + public async handleFile( + file: Blob + ): Promise<{ fileType: 'overview' } | { fileType: 'comparison'; id1: string; id2: string }> { + const content = await file.text() + const json = JSON.parse(content) + + store().setSingleFileRawContent(content) + if (json['submission_folder_path']) { + return { fileType: 'overview' } + } else if (json['id1'] && json['id2']) { + return { fileType: 'comparison', id1: json['id1'], id2: json['id2'] } + } else { + throw new Error(`Invalid JSON: ${json}`) + } + } +} diff --git a/report-viewer/src/utils/fileHandling/ZipFileHandler.ts b/report-viewer/src/utils/fileHandling/ZipFileHandler.ts new file mode 100644 index 000000000..5702d2bac --- /dev/null +++ b/report-viewer/src/utils/fileHandling/ZipFileHandler.ts @@ -0,0 +1,107 @@ +import { store } from '@/stores/store' +import jszip from 'jszip' +import slash from 'slash' +import { FileHandler } from './FileHandler' + +/** + * Class for handling zip files. + */ +export class ZipFileHandler extends FileHandler { + public async handleFile(file: Blob): Promise { + console.log('Start handling zip file and storing necessary data...') + return jszip.loadAsync(file).then(async (zip) => { + for (const originalFileName of Object.keys(zip.files)) { + const unixFileName = slash(originalFileName) + if ( + /((.+\/)*)(files|submissions)\/(.+)\/(.+)/.test(unixFileName) && + !/^__MACOSX\//.test(unixFileName) + ) { + const directoryPath = unixFileName.substring(0, unixFileName.lastIndexOf('/')) + const fileBase = unixFileName.substring(unixFileName.lastIndexOf('/') + 1) + + const submissionFileName = this.extractSubmissionFileName(directoryPath) + const fullPathFileName = this.extractFileNameWithFullPath( + directoryPath, + fileBase, + originalFileName + ) + await zip.files[originalFileName].async('string').then((data) => { + store().saveSubmissionFile({ + submissionId: slash(submissionFileName), + fileName: slash(fullPathFileName), + data: data + }) + }) + } else { + await zip.files[originalFileName].async('string').then((data) => { + store().saveFile({ fileName: unixFileName, data: data }) + }) + } + } + }) + } + + /** + * Extracts the submission file name from the given directory path. + * @param directoryPath Path to extract the submission file name from. + */ + private extractSubmissionFileName(directoryPath: string) { + const folders = directoryPath.split('/') + const rootName = folders[0] + let submissionFolderIndex = -1 + if (rootName === 'files') { + submissionFolderIndex = folders.findIndex((folder) => folder === 'files') + } else { + submissionFolderIndex = folders.findIndex((folder) => folder === 'submissions') + } + return folders[submissionFolderIndex + 1] + } + + /** + * Gets the full path of the file + * @param directoryPath Path to the file + * @param fileBase Name of the file + * @param originalFileName Original name of the file + */ + private extractFileNameWithFullPath( + directoryPath: string, + fileBase: string, + originalFileName: string + ) { + let fullPath = '' + const rootName = this.extractRootName(directoryPath) + const filesOrSubmissionsIndex_filePath = directoryPath.indexOf( + rootName === 'files' ? 'files' : 'submissions' + ) + const filesOrSubmissionsIndex_originalFileName = originalFileName.indexOf( + rootName === 'files' ? 'files' : 'submissions' + ) + const unixSubfolderPathAfterSubmissions = directoryPath.substring( + filesOrSubmissionsIndex_filePath + + (rootName === 'files' ? 'files'.length : 'submissions'.length) + + 1 + ) + const originalPathWithoutSubmissions = originalFileName.substring( + filesOrSubmissionsIndex_originalFileName + + (rootName === 'files' ? 'files'.length : 'submissions'.length) + ) + if (originalPathWithoutSubmissions.charAt(0) === '\\') { + fullPath = unixSubfolderPathAfterSubmissions + '\\' + fileBase + while (fullPath.includes('/')) { + fullPath = fullPath.replace('/', '\\') + } + } else { + fullPath = unixSubfolderPathAfterSubmissions + '/' + fileBase + } + return fullPath + } + + /** + * Gets the root name of the given directory path. + * @param directoryPath Path to extract the root name from. + */ + private extractRootName(directoryPath: string) { + const folders = directoryPath.split('/') + return folders[0] + } +} diff --git a/report-viewer/src/version.json b/report-viewer/src/version.json index 1b174cd51..0841e990d 100644 --- a/report-viewer/src/version.json +++ b/report-viewer/src/version.json @@ -4,4 +4,4 @@ "minor": 0, "patch": 0 } -} \ No newline at end of file +} diff --git a/report-viewer/src/viewWrapper/ClusterViewWrapper.vue b/report-viewer/src/viewWrapper/ClusterViewWrapper.vue new file mode 100644 index 000000000..d3cf2a2aa --- /dev/null +++ b/report-viewer/src/viewWrapper/ClusterViewWrapper.vue @@ -0,0 +1,32 @@ + + + diff --git a/report-viewer/src/viewWrapper/ComparisonViewWrapper.vue b/report-viewer/src/viewWrapper/ComparisonViewWrapper.vue new file mode 100644 index 000000000..96395207b --- /dev/null +++ b/report-viewer/src/viewWrapper/ComparisonViewWrapper.vue @@ -0,0 +1,49 @@ + + + diff --git a/report-viewer/src/viewWrapper/InformationViewWrapper.vue b/report-viewer/src/viewWrapper/InformationViewWrapper.vue new file mode 100644 index 000000000..6354e8630 --- /dev/null +++ b/report-viewer/src/viewWrapper/InformationViewWrapper.vue @@ -0,0 +1,23 @@ + + + diff --git a/report-viewer/src/viewWrapper/OverviewViewWrapper.vue b/report-viewer/src/viewWrapper/OverviewViewWrapper.vue new file mode 100644 index 000000000..c7c4f07d3 --- /dev/null +++ b/report-viewer/src/viewWrapper/OverviewViewWrapper.vue @@ -0,0 +1,23 @@ + + + diff --git a/report-viewer/src/views/ClusterView.vue b/report-viewer/src/views/ClusterView.vue new file mode 100644 index 000000000..11dcc3d7f --- /dev/null +++ b/report-viewer/src/views/ClusterView.vue @@ -0,0 +1,97 @@ + + + diff --git a/report-viewer/src/views/ComparisonView.vue b/report-viewer/src/views/ComparisonView.vue index 51116be5e..a50bd1746 100644 --- a/report-viewer/src/views/ComparisonView.vue +++ b/report-viewer/src/views/ComparisonView.vue @@ -2,363 +2,181 @@ A view displaying the .json file of a comparison from a JPlag report. --> - - - diff --git a/report-viewer/src/views/ErrorView.vue b/report-viewer/src/views/ErrorView.vue index b571c4e95..d9e010720 100644 --- a/report-viewer/src/views/ErrorView.vue +++ b/report-viewer/src/views/ErrorView.vue @@ -1,40 +1,39 @@ - - - \ No newline at end of file diff --git a/report-viewer/src/views/FileUploadView.vue b/report-viewer/src/views/FileUploadView.vue index a9785e11f..c6a95c50c 100644 --- a/report-viewer/src/views/FileUploadView.vue +++ b/report-viewer/src/views/FileUploadView.vue @@ -2,252 +2,220 @@ Starting view of the application. Presents the options for loading a JPlag report. --> - +const hasMoreSubmissionPaths = computed(() => props.overview.submissionFolderPath.length > 1) +const submissionPathValue = computed(() => + hasMoreSubmissionPaths.value + ? 'Click More to see all paths' + : props.overview.submissionFolderPath[0] +) + +onErrorCaptured((e) => { + console.log(e) + router.push({ + name: 'ErrorView', + state: { + message: 'Overview.json could not be found!', + to: '/', + routerInfo: 'back to FileUpload page' + } + }) + store().clearStore() + return false +}) + diff --git a/report-viewer/src/vue-virtual-scroll.d.ts b/report-viewer/src/vue-virtual-scroll.d.ts index ee9239e91..70ffe2eea 100644 --- a/report-viewer/src/vue-virtual-scroll.d.ts +++ b/report-viewer/src/vue-virtual-scroll.d.ts @@ -1,22 +1,22 @@ // Type definitions for vue-virtual-scroller // Project: https://github.com/Akryum/vue-virtual-scroller/ // Reference: https://github.com/Akryum/vue-virtual-scroller/issues/199 -declare module "vue-virtual-scroller" { - import Vue, { ComponentOptions, PluginObject, Component } from "vue"; - interface PluginOptions { - installComponents?: boolean; - componentsPrefix?: string; - } +declare module 'vue-virtual-scroller' { + import Vue, { ComponentOptions, PluginObject, Component } from 'vue' + interface PluginOptions { + installComponents?: boolean + componentsPrefix?: string + } - const plugin: PluginObject & { version: string }; + const plugin: PluginObject & { version: string } - export const RecycleScroller: Component; - export const DynamicScroller: Component; - export const DynamicScrollerItem: Component; + export const RecycleScroller: Component + export const DynamicScroller: Component + export const DynamicScrollerItem: Component - export function IdState(options?: { - idProp?: (vm: any) => any; - }): ComponentOptions | typeof Vue; + export function IdState(options?: { + idProp?: (vm: any) => any + }): ComponentOptions | typeof Vue - export default plugin; -} \ No newline at end of file + export default plugin +} diff --git a/report-viewer/tailwind.config.js b/report-viewer/tailwind.config.js new file mode 100644 index 000000000..b32cc4100 --- /dev/null +++ b/report-viewer/tailwind.config.js @@ -0,0 +1,64 @@ +import colors from 'tailwindcss/colors' + +/** @type {import('tailwindcss').Config} */ +export default { + darkMode: 'class', + content: ['./index.html', './src/**/*.{js,ts,vue}'], + theme: { + extend: { + colors: { + font: { + light: '#000000', + dark: '#ffffff' + }, + backgorund: { + light: 'hsl(0, 0%, 97%)', + dark: 'hsl(180, 80%, 3%)' + }, + container: { + light: 'hsl(0, 0%, 98%)', + dark: 'hsl(200, 20%, 13%)', + border: { + light: 'hsl(0, 0%, 80%)', + dark: 'hsl(0, 0%, 25%)' + }, + secondary: { + light: 'hsl(0, 0%, 95%)', + dark: 'hsl(200, 20%, 18%)' + } + }, + interactable: { + light: 'hsl(0, 0%, 100%)', + dark: 'hsl(180, 30%, 18%)', + border: { + light: 'hsl(0, 0%, 75%)', + dark: 'hsl(0, 0%, 30%)' + } + }, + scrollbar: { + backgorund: { + light: colors.slate[100], + dark: '#30363D' + }, + thumb: { + light: colors.slate[400], + dark: '#505A66' + } + }, + accent: { + DEFAULT: '#be1622', + dark: '#7F0F18' + }, + link: { + DEFAULT: '#0070f3', + dark: '#00c' + }, + error: '#dc322f' + }, + borderWidth: { + 1: '1px' + } + } + }, + plugins: [] +} diff --git a/report-viewer/tests/e2e/boilerplate.spec.ts b/report-viewer/tests/e2e/boilerplate.spec.ts new file mode 100644 index 000000000..556c07088 --- /dev/null +++ b/report-viewer/tests/e2e/boilerplate.spec.ts @@ -0,0 +1,5 @@ +import { test } from '@playwright/test' + +test('example', async ({ page }) => { + await page.goto('/') +}) diff --git a/report-viewer/tests/e2e/tsconfig.json b/report-viewer/tests/e2e/tsconfig.json new file mode 100644 index 000000000..239accd1c --- /dev/null +++ b/report-viewer/tests/e2e/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@vue/tsconfig/tsconfig.node.json", + "include": ["./**/*"] +} diff --git a/report-viewer/tests/unit/boilderplate.test.ts b/report-viewer/tests/unit/boilderplate.test.ts new file mode 100644 index 000000000..51aa373be --- /dev/null +++ b/report-viewer/tests/unit/boilderplate.test.ts @@ -0,0 +1,15 @@ +import { describe, test, it, beforeEach } from 'vitest' +import { setActivePinia, createPinia } from 'pinia' + +test('example_unit', async () => {}) + +describe('example_component', () => { + beforeEach(() => { + setActivePinia(createPinia()) + }) + + it('example_1_component', () => { + // expect(ComponentName).toBeTruthy() + // const wrapper = mount(ComponentName, { + }) +}) diff --git a/report-viewer/tests/unit/components/LineOfCode.spec.ts b/report-viewer/tests/unit/components/LineOfCode.spec.ts deleted file mode 100644 index 1be85831d..000000000 --- a/report-viewer/tests/unit/components/LineOfCode.spec.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { shallowMount } from '@vue/test-utils' -import LineOfCode from '@/components/LineOfCode.vue' - -test("loc", () => { - const wrapper = shallowMount(LineOfCode, { - props: { - visible: true, - text: "Hello World", - lineNumber: 3, - color: "white" - } - }); - const preText = wrapper.find({ ref: 'lineRef'}); - expect(preText.text()).toContain('Hello World'); - expect(preText.text()).toContain('3'); - - wrapper.vm.$emit('lineSelected'); - expect(wrapper.emitted().lineSelected).toBeTruthy(); -}) \ No newline at end of file diff --git a/report-viewer/tests/unit/components/MatchTable.spec.ts b/report-viewer/tests/unit/components/MatchTable.spec.ts deleted file mode 100644 index b53bc86ae..000000000 --- a/report-viewer/tests/unit/components/MatchTable.spec.ts +++ /dev/null @@ -1,26 +0,0 @@ -import {shallowMount} from '@vue/test-utils' -import MatchTable from "@/components/MatchTable.vue"; -import store from "@/store/store"; - -beforeEach(()=>{ - let fileIdToDisplayNameMap = store.state.fileIdToDisplayName; - fileIdToDisplayNameMap.set("A","A"); - fileIdToDisplayNameMap.set("C","C"); -}) - -test("MT", () => { - const wrapper = shallowMount(MatchTable,{ - props: { - id1: "A", - id2: "C", - matches: [{firstFile:"A\\GSTiling.java",secondFile:"C\\GSTiling.java",startInFirst:6,endInFirst:247,startInSecond:13,endInSecond:254,tokens:345,color:"\\hsla(0, 80%, 50%, 0.3)"}], - }, - }); - const matchesInfo = wrapper.findAll(".td-content p"); - expect(matchesInfo[0].text()).toContain("A\\GSTiling.java"); - expect(matchesInfo[1].text()).toContain("(6 - 247)"); - expect(matchesInfo[2].text()).toContain("C\\GSTiling.java"); - expect(matchesInfo[3].text()).toContain("(13 - 254)"); - const matchToken = wrapper.findAll("td"); - expect(parseInt(matchToken[2].text())).toBe(345); -}) \ No newline at end of file diff --git a/report-viewer/tests/unit/components/VersionInfoComponent.test.ts b/report-viewer/tests/unit/components/VersionInfoComponent.test.ts new file mode 100644 index 000000000..e27c4c563 --- /dev/null +++ b/report-viewer/tests/unit/components/VersionInfoComponent.test.ts @@ -0,0 +1,55 @@ +import VersionInfoComponent from '@/components/VersionInfoComponent.vue' +import { flushPromises, mount } from '@vue/test-utils' +import { describe, it, vi, expect } from 'vitest' +import version from '@/version.json' + +vi.mock('@/version.json') + +describe('VersionInfoComponent', () => { + it('Render develop version', async () => { + version.report_viewer_version = mockVersionJSON(0, 0, 0) + global.fetch = vi.fn().mockResolvedValueOnce(mockVersionResponse('v4.3.0')) + + const wrapper = mount(VersionInfoComponent) + await flushPromises() + + expect(wrapper.text()).toContain('development version') + }) + + it('Render outdated version', async () => { + version.report_viewer_version = mockVersionJSON(4, 3, 0) + global.fetch = vi.fn().mockResolvedValueOnce(mockVersionResponse('v4.4.0')) + + const wrapper = mount(VersionInfoComponent) + await flushPromises() + + expect(wrapper.text()).toContain('outdated version') + }) + + it('Render latest version', async () => { + version.report_viewer_version = mockVersionJSON(4, 3, 0) + global.fetch = vi.fn().mockResolvedValueOnce(mockVersionResponse('v4.3.0')) + + const wrapper = mount(VersionInfoComponent) + await flushPromises() + + expect(wrapper.text()).toContain('JPlag v4.3.0') + }) +}) + +function mockVersionResponse(version: string) { + return { + json: () => + Promise.resolve({ + tag_name: version + }) + } +} + +function mockVersionJSON(major: number, minor: number, patch: number) { + return { + major: major, + minor: minor, + patch: patch + } +} diff --git a/report-viewer/tests/unit/components/optionsSelectors/MetricSelector.test.ts b/report-viewer/tests/unit/components/optionsSelectors/MetricSelector.test.ts new file mode 100644 index 000000000..304100bf1 --- /dev/null +++ b/report-viewer/tests/unit/components/optionsSelectors/MetricSelector.test.ts @@ -0,0 +1,45 @@ +import { describe, expect, it } from 'vitest' +import { mount } from '@vue/test-utils' +import MetricSelector from '@/components/optionsSelectors/MetricSelector.vue' +import { MetricType } from '@/model/MetricType' + +describe('OptionSelectorComponent', () => { + it('renders all options', async () => { + const wrapper = mount(MetricSelector, { + props: { + title: 'Test:' + } + }) + + expect(wrapper.text()).toContain('Test:') + expect(wrapper.text()).toContain('Average Similarity') + expect(wrapper.text()).toContain('Maximum Similarity') + }) + + it('renders given metrics only', async () => { + const wrapper = mount(MetricSelector, { + props: { + title: 'Test:', + metrics: [MetricType.AVERAGE] + } + }) + + expect(wrapper.text()).toContain('Test:') + expect(wrapper.text()).toContain('Average Similarity') + expect(wrapper.text()).not.toContain('Maximum Similarity') + }) + + it('switch selection', async () => { + const wrapper = mount(MetricSelector, { + props: { + title: 'Test:' + } + }) + + await wrapper.findAllComponents({ name: 'OptionComponent' })[1].trigger('click') + + expect(wrapper.emitted('selectionChanged')).toBeTruthy() + expect(wrapper.emitted('selectionChanged')?.length).toBe(1) + expect(wrapper.emitted('selectionChanged')?.[0]).toEqual([MetricType.MAXIMUM]) + }) +}) diff --git a/report-viewer/tests/unit/components/optionsSelectors/OptionSelectorComponent.test.ts b/report-viewer/tests/unit/components/optionsSelectors/OptionSelectorComponent.test.ts new file mode 100644 index 000000000..8947c8050 --- /dev/null +++ b/report-viewer/tests/unit/components/optionsSelectors/OptionSelectorComponent.test.ts @@ -0,0 +1,70 @@ +import { describe, expect, it } from 'vitest' +import { mount } from '@vue/test-utils' +import OptionsSelectorComponent from '@/components/optionsSelectors/OptionsSelectorComponent.vue' +import OptionComponent from '@/components/optionsSelectors/OptionComponent.vue' + +describe('OptionSelectorComponent', () => { + it('renders all options', async () => { + const wrapper = mount(OptionsSelectorComponent, { + props: { + title: 'Test:', + labels: ['Option 1', 'Option 2', 'Option 3'], + defaultSelected: 1 + } + }) + + expect(wrapper.text()).toContain('Test:') + expect(wrapper.text()).toContain('Option 1') + expect(wrapper.text()).toContain('Option 2') + expect(wrapper.text()).toContain('Option 3') + + expect( + wrapper + .findAllComponents(OptionComponent) + .find((e) => e.text() === 'Option 2') + ?.classes() + ).toContain('!bg-accent') + }) + + it('switch selection', async () => { + const wrapper = mount(OptionsSelectorComponent, { + props: { + title: 'Test:', + labels: ['Option 1', 'Option 2'], + defaultSelected: 0 + } + }) + + expect( + wrapper + .findAllComponents(OptionComponent) + .find((e) => e.text() === 'Option 1') + ?.classes() + ).toContain('!bg-accent') + expect( + wrapper + .findAllComponents(OptionComponent) + .find((e) => e.text() === 'Option 2') + ?.classes() + ).not.toContain('!bg-accent') + + await wrapper.findAllComponents({ name: 'OptionComponent' })[1].trigger('click') + + expect(wrapper.emitted('selectionChanged')).toBeTruthy() + expect(wrapper.emitted('selectionChanged')?.length).toBe(1) + expect(wrapper.emitted('selectionChanged')?.[0]).toEqual([1]) + + expect( + wrapper + .findAllComponents(OptionComponent) + .find((e) => e.text() === 'Option 1') + ?.classes() + ).not.toContain('!bg-accent') + expect( + wrapper + .findAll('.cursor-pointer') + .find((e) => e.text() === 'Option 2') + ?.classes() + ).toContain('!bg-accent') + }) +}) diff --git a/report-viewer/tests/unit/model/Comparison.spec.ts b/report-viewer/tests/unit/model/Comparison.spec.ts deleted file mode 100644 index 5a29caaab..000000000 --- a/report-viewer/tests/unit/model/Comparison.spec.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Comparison } from "@/model/Comparison"; - -test('comparison similarity should be saved as is', () => { - const comparison = new Comparison("studentA", "studentB", 0.5); - expect(comparison.similarity).toBe(0.5); -}) \ No newline at end of file diff --git a/report-viewer/tests/unit/model/Distribution.test.ts b/report-viewer/tests/unit/model/Distribution.test.ts new file mode 100644 index 000000000..f5b6fa301 --- /dev/null +++ b/report-viewer/tests/unit/model/Distribution.test.ts @@ -0,0 +1,18 @@ +import { describe, expect, it } from 'vitest' +import { Distribution } from '@/model/Distribution' +import { TenValueDistribution } from '@/model/TenValueDistribution' +import { HundredValueDistribution } from '@/model/HundredValueDistribution' + +describe('Distribution', () => { + it.each([ + new TenValueDistribution([0, 0, 0, 0, 0, 0, 26, 13209, 58955, 5231]), + new HundredValueDistribution([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 1, 0, 1, 2, 12, 8, 31, 61, 168, 273, 493, 923, 1544, 2244, 3163, 4309, 5373, 6343, 7177, + 7445, 7292, 7023, 6130, 5091, 4056, 3025, 2052, 1442, 869, 470, 225, 109, 42, 15, 7, 0 + ]) + ])('get in 10 Buckets', (distribution: Distribution) => { + expect(distribution.splitIntoTenBuckets()).toEqual([0, 0, 0, 0, 0, 0, 26, 13209, 58955, 5231]) + }) +}) diff --git a/report-viewer/tests/unit/model/Overview.spec.ts b/report-viewer/tests/unit/model/Overview.spec.ts deleted file mode 100644 index 8b064c724..000000000 --- a/report-viewer/tests/unit/model/Overview.spec.ts +++ /dev/null @@ -1,157 +0,0 @@ -import {Overview} from "@/model/Overview"; -import {Metric} from "@/model/Metric"; -import {Cluster} from "@/model/Cluster"; -test('overview', () => { - const submissionFolderPath:Array = ["C:\\Users\\23651\\Desktop\\JPlag\\core\\src\\test\\resources\\de\\jplag\\samples\\PartialPlagiarism"] - const baseCodeFolderPath = ""; - const language = "Javac based AST plugin"; - const fileExtensions: Array = [".java",".JAVA"]; - const matchSensitivity = 9; - const dateOfExecution = "14/12/22"; - const durationOfExecution = 40; - const metrics: Array = [{ - "metricName": "AVG", - "distribution": [1, 0, 2, 0, 0, 0, 0, 3, 0, 4], - "metricThreshold": 0, - "comparisons": [ - { "id": 1, - "firstSubmissionId": "A", - "secondSubmissionId": "C", - "similarity": 0.9966329966329966 - }, - { - "id": 2, - "firstSubmissionId": "D", - "secondSubmissionId": "A", - "similarity": 0.7787255393878575 - }, - { - "id": 3, - "firstSubmissionId": "D", - "secondSubmissionId": "C", - "similarity": 0.7787255393878575 - }, - { - "id": 4, - "firstSubmissionId": "B", - "secondSubmissionId": "D", - "similarity": 0.2827868852459016 - }, - { - "id": 5, - "firstSubmissionId": "B", - "secondSubmissionId": "A", - "similarity": 0.2457689477557027 - }, - { - "id": 6, - "firstSubmissionId": "B", - "secondSubmissionId": "C", - "similarity": 0.2457689477557027 - }, - { - "id": 7, - "firstSubmissionId": "E", - "secondSubmissionId": "A", - "similarity": 0 - }, - { - "id": 8, - "firstSubmissionId": "E", - "secondSubmissionId": "D", - "similarity": 0 - }, - { - "id": 9, - "firstSubmissionId": "E", - "secondSubmissionId": "B", - "similarity": 0 - }, - { - "id": 10, - "firstSubmissionId": "E", - "secondSubmissionId": "C", - "similarity": 0 - } - ], - "description": "Average of both program coverages. This is the default similarity which works in most cases: Matches with a high average similarity indicate that the programs work in a very similar way." - },{ - "metricName": "MAX", - "distribution": [5, 1, 0, 0, 0, 0, 0, 0, 0, 4], - "metricThreshold": 0, - "comparisons": [ - { - "id": 1, - "firstSubmissionId": "A", - "secondSubmissionId": "C", - "similarity": 0.9966329966329966 - }, - { - "id": 2, - "firstSubmissionId": "B", - "secondSubmissionId": "A", - "similarity": 0.9766081871345029 - }, - { - "id": 3, - "firstSubmissionId": "B", - "secondSubmissionId": "C", - "similarity": 0.9766081871345029 - }, - { - "id": 4, - "firstSubmissionId": "D", - "secondSubmissionId": "A", - "similarity": 0.9639751552795031 - }, - { - "id": 5, - "firstSubmissionId": "D", - "secondSubmissionId": "C", - "similarity": 0.9639751552795031 - }, - { - "id": 6, - "firstSubmissionId": "B", - "secondSubmissionId": "D", - "similarity": 0.8070175438596491 - }, - { - "id": 7, - "firstSubmissionId": "E", - "secondSubmissionId": "A", - "similarity": 0 - }, - { - "id": 8, - "firstSubmissionId": "E", - "secondSubmissionId": "D", - "similarity": 0 - }, - { - "id": 9, - "firstSubmissionId": "E", - "secondSubmissionId": "B", - "similarity": 0 - }, - { - "id": 10, - "firstSubmissionId": "E", - "secondSubmissionId": "C", - "similarity": 0 - } - ], - "description": "Maximum of both program coverages. This ranking is especially useful if the programs are very different in size. This can happen when dead code was inserted to disguise the origin of the plagiarized program." - }]; - const clusters: Array = []; - const submissionIdsToComparisonFileName: Map> = new Map>(); - const overview: Overview = new Overview(submissionFolderPath,baseCodeFolderPath,language,fileExtensions,matchSensitivity, - dateOfExecution,durationOfExecution,metrics,clusters,10,submissionIdsToComparisonFileName); - expect(overview.language).toMatch("Javac based AST plugin"); - expect(overview.matchSensitivity).toBe(9); - expect(overview.dateOfExecution).toMatch("14/12/22"); - expect(overview.durationOfExecution).toBe(40); - expect(overview.metrics.length).toBe(2); - expect(overview.metrics[0].metricName).toMatch("AVG"); - expect(overview.metrics[1].metricName).toMatch("MAX"); -}) \ No newline at end of file diff --git a/report-viewer/tests/unit/model/factories/ComparisonFactory.spec.ts b/report-viewer/tests/unit/model/factories/ComparisonFactory.spec.ts deleted file mode 100644 index d16e80ac2..000000000 --- a/report-viewer/tests/unit/model/factories/ComparisonFactory.spec.ts +++ /dev/null @@ -1,71 +0,0 @@ -import store from "@/store/store"; -import {ComparisonFactory} from "@/model/factories/ComparisonFactory"; - - -beforeEach(() => { - store.replaceState({ - "submissionIdsToComparisonFileName": new Map>(), - "anonymous": new Set(), - "files": { - "A-C.json": "{\"id1\":\"A\",\"id2\":\"C\",\"similarity\":0.9966329966329966,\"matches\":[{\"file1\":\"A\\\\GSTiling.java\",\"file2\":\"C\\\\GSTiling.java\",\"start1\":6,\"end1\":247,\"start2\":6,\"end2\":247,\"tokens\":345},{\"file1\":\"A\\\\Submission.java\",\"file2\":\"C\\\\Submission.java\",\"start1\":1,\"end1\":218,\"start2\":1,\"end2\":218,\"tokens\":324},{\"file1\":\"A\\\\Structure.java\",\"file2\":\"C\\\\Structure.java\",\"start1\":1,\"end1\":118,\"start2\":1,\"end2\":118,\"tokens\":174},{\"file1\":\"A\\\\Match.java\",\"file2\":\"C\\\\Match.java\",\"start1\":1,\"end1\":51,\"start2\":1,\"end2\":51,\"tokens\":104},{\"file1\":\"A\\\\Table.java\",\"file2\":\"C\\\\Table.java\",\"start1\":5,\"end1\":60,\"start2\":5,\"end2\":60,\"tokens\":92},{\"file1\":\"A\\\\Token.java\",\"file2\":\"C\\\\Token.java\",\"start1\":1,\"end1\":47,\"start2\":1,\"end2\":47,\"tokens\":75},{\"file1\":\"A\\\\Matches.java\",\"file2\":\"C\\\\Matches.java\",\"start1\":3,\"end1\":57,\"start2\":3,\"end2\":57,\"tokens\":70}]}", - "B-A.json": "{\"id1\":\"B\",\"id2\":\"A\",\"similarity\":0.2457689477557027,\"matches\":[{\"file1\":\"B\\\\Table.java\",\"file2\":\"A\\\\Table.java\",\"start1\":5,\"end1\":60,\"start2\":5,\"end2\":60,\"tokens\":92},{\"file1\":\"B\\\\Token.java\",\"file2\":\"A\\\\Token.java\",\"start1\":1,\"end1\":47,\"start2\":1,\"end2\":47,\"tokens\":75}]}", - "B-C.json": "{\"id1\":\"B\",\"id2\":\"C\",\"similarity\":0.2457689477557027,\"matches\":[{\"file1\":\"B\\\\Table.java\",\"file2\":\"C\\\\Table.java\",\"start1\":5,\"end1\":60,\"start2\":5,\"end2\":60,\"tokens\":92},{\"file1\":\"B\\\\Token.java\",\"file2\":\"C\\\\Token.java\",\"start1\":1,\"end1\":47,\"start2\":1,\"end2\":47,\"tokens\":75}]}", - "B-D.json": "{\"id1\":\"B\",\"id2\":\"D\",\"similarity\":0.2827868852459016,\"matches\":[{\"file1\":\"B\\\\Token.java\",\"file2\":\"D\\\\Token.java\",\"start1\":16,\"end1\":47,\"start2\":14,\"end2\":44,\"tokens\":59},{\"file1\":\"B\\\\Table.java\",\"file2\":\"D\\\\Table.java\",\"start1\":30,\"end1\":60,\"start2\":22,\"end2\":52,\"tokens\":50},{\"file1\":\"B\\\\Table.java\",\"file2\":\"D\\\\Table.java\",\"start1\":5,\"end1\":21,\"start2\":5,\"end2\":21,\"tokens\":29}]}", - "D-A.json": "{\"id1\":\"D\",\"id2\":\"A\",\"similarity\":0.7787255393878575,\"matches\":[{\"file1\":\"D\\\\Structure.java\",\"file2\":\"A\\\\Structure.java\",\"start1\":3,\"end1\":120,\"start2\":1,\"end2\":118,\"tokens\":174},{\"file1\":\"D\\\\Submission.java\",\"file2\":\"A\\\\Submission.java\",\"start1\":3,\"end1\":111,\"start2\":1,\"end2\":109,\"tokens\":146},{\"file1\":\"D\\\\Match.java\",\"file2\":\"A\\\\Match.java\",\"start1\":3,\"end1\":53,\"start2\":1,\"end2\":51,\"tokens\":104},{\"file1\":\"D\\\\Matches.java\",\"file2\":\"A\\\\Matches.java\",\"start1\":5,\"end1\":59,\"start2\":3,\"end2\":57,\"tokens\":70},{\"file1\":\"D\\\\Token.java\",\"file2\":\"A\\\\Token.java\",\"start1\":14,\"end1\":44,\"start2\":16,\"end2\":47,\"tokens\":59},{\"file1\":\"D\\\\Table.java\",\"file2\":\"A\\\\Table.java\",\"start1\":22,\"end1\":52,\"start2\":30,\"end2\":60,\"tokens\":50},{\"file1\":\"D\\\\Submission.java\",\"file2\":\"A\\\\Submission.java\",\"start1\":165,\"end1\":194,\"start2\":173,\"end2\":203,\"tokens\":42},{\"file1\":\"D\\\\Submission.java\",\"file2\":\"A\\\\Submission.java\",\"start1\":129,\"end1\":155,\"start2\":134,\"end2\":160,\"tokens\":41},{\"file1\":\"D\\\\Submission.java\",\"file2\":\"A\\\\Submission.java\",\"start1\":112,\"end1\":127,\"start2\":116,\"end2\":132,\"tokens\":30},{\"file1\":\"D\\\\Table.java\",\"file2\":\"A\\\\Table.java\",\"start1\":5,\"end1\":21,\"start2\":5,\"end2\":21,\"tokens\":29},{\"file1\":\"D\\\\Submission.java\",\"file2\":\"A\\\\Submission.java\",\"start1\":156,\"end1\":163,\"start2\":164,\"end2\":171,\"tokens\":18},{\"file1\":\"D\\\\Submission.java\",\"file2\":\"A\\\\Submission.java\",\"start1\":195,\"end1\":202,\"start2\":204,\"end2\":211,\"tokens\":13}]}", - "D-C.json": "{\"id1\":\"D\",\"id2\":\"C\",\"similarity\":0.7787255393878575,\"matches\":[{\"file1\":\"D\\\\Structure.java\",\"file2\":\"C\\\\Structure.java\",\"start1\":3,\"end1\":120,\"start2\":1,\"end2\":118,\"tokens\":174},{\"file1\":\"D\\\\Submission.java\",\"file2\":\"C\\\\Submission.java\",\"start1\":3,\"end1\":111,\"start2\":1,\"end2\":109,\"tokens\":146},{\"file1\":\"D\\\\Match.java\",\"file2\":\"C\\\\Match.java\",\"start1\":3,\"end1\":53,\"start2\":1,\"end2\":51,\"tokens\":104},{\"file1\":\"D\\\\Matches.java\",\"file2\":\"C\\\\Matches.java\",\"start1\":5,\"end1\":59,\"start2\":3,\"end2\":57,\"tokens\":70},{\"file1\":\"D\\\\Token.java\",\"file2\":\"C\\\\Token.java\",\"start1\":14,\"end1\":44,\"start2\":16,\"end2\":47,\"tokens\":59},{\"file1\":\"D\\\\Table.java\",\"file2\":\"C\\\\Table.java\",\"start1\":22,\"end1\":52,\"start2\":30,\"end2\":60,\"tokens\":50},{\"file1\":\"D\\\\Submission.java\",\"file2\":\"C\\\\Submission.java\",\"start1\":165,\"end1\":194,\"start2\":173,\"end2\":203,\"tokens\":42},{\"file1\":\"D\\\\Submission.java\",\"file2\":\"C\\\\Submission.java\",\"start1\":129,\"end1\":155,\"start2\":134,\"end2\":160,\"tokens\":41},{\"file1\":\"D\\\\Submission.java\",\"file2\":\"C\\\\Submission.java\",\"start1\":112,\"end1\":127,\"start2\":116,\"end2\":132,\"tokens\":30},{\"file1\":\"D\\\\Table.java\",\"file2\":\"C\\\\Table.java\",\"start1\":5,\"end1\":21,\"start2\":5,\"end2\":21,\"tokens\":29},{\"file1\":\"D\\\\Submission.java\",\"file2\":\"C\\\\Submission.java\",\"start1\":156,\"end1\":163,\"start2\":164,\"end2\":171,\"tokens\":18},{\"file1\":\"D\\\\Submission.java\",\"file2\":\"C\\\\Submission.java\",\"start1\":195,\"end1\":202,\"start2\":204,\"end2\":211,\"tokens\":13}]}", - "E-A.json": "{\"id1\":\"E\",\"id2\":\"A\",\"similarity\":0.0,\"matches\":[]}", - "E-B.json": "{\"id1\":\"E\",\"id2\":\"B\",\"similarity\":0.0,\"matches\":[]}", - "E-C.json": "{\"id1\":\"E\",\"id2\":\"C\",\"similarity\":0.0,\"matches\":[]}", - "E-D.json": "{\"id1\":\"E\",\"id2\":\"D\",\"similarity\":0.0,\"matches\":[]}", - "overview.json": "{\"jplag_version\":{\"major\":0,\"minor\":0,\"patch\":0},\"submission_folder_path\":[\"C:\\\\Users\\\\23651\\\\Desktop\\\\JPlag\\\\core\\\\src\\\\test\\\\resources\\\\de\\\\jplag\\\\samples\\\\PartialPlagiarism\"],\"base_code_folder_path\":\"\",\"language\":\"Javac based AST plugin\",\"file_extensions\":[\".java\",\".JAVA\"],\"submission_id_to_display_name\":{\"A\":\"A\",\"B\":\"B\",\"C\":\"C\",\"D\":\"D\",\"E\":\"E\"},\"submission_ids_to_comparison_file_name\":{\"A\":{\"B\":\"B-A.json\",\"C\":\"A-C.json\",\"D\":\"D-A.json\",\"E\":\"E-A.json\"},\"B\":{\"A\":\"B-A.json\",\"C\":\"B-C.json\",\"D\":\"B-D.json\",\"E\":\"E-B.json\"},\"C\":{\"A\":\"A-C.json\",\"B\":\"B-C.json\",\"D\":\"D-C.json\",\"E\":\"E-C.json\"},\"D\":{\"A\":\"D-A.json\",\"B\":\"B-D.json\",\"C\":\"D-C.json\",\"E\":\"E-D.json\"},\"E\":{\"A\":\"E-A.json\",\"B\":\"E-B.json\",\"C\":\"E-C.json\",\"D\":\"E-D.json\"}},\"failed_submission_names\":[],\"excluded_files\":[],\"match_sensitivity\":9,\"date_of_execution\":\"14/12/22\",\"execution_time\":40,\"metrics\":[{\"name\":\"AVG\",\"distribution\":[1,0,2,0,0,0,0,3,0,4],\"topComparisons\":[{\"first_submission\":\"A\",\"second_submission\":\"C\",\"similarity\":0.9966329966329966},{\"first_submission\":\"D\",\"second_submission\":\"A\",\"similarity\":0.7787255393878575},{\"first_submission\":\"D\",\"second_submission\":\"C\",\"similarity\":0.7787255393878575},{\"first_submission\":\"B\",\"second_submission\":\"D\",\"similarity\":0.2827868852459016},{\"first_submission\":\"B\",\"second_submission\":\"A\",\"similarity\":0.2457689477557027},{\"first_submission\":\"B\",\"second_submission\":\"C\",\"similarity\":0.2457689477557027},{\"first_submission\":\"E\",\"second_submission\":\"A\",\"similarity\":0.0},{\"first_submission\":\"E\",\"second_submission\":\"D\",\"similarity\":0.0},{\"first_submission\":\"E\",\"second_submission\":\"B\",\"similarity\":0.0},{\"first_submission\":\"E\",\"second_submission\":\"C\",\"similarity\":0.0}],\"description\":\"Average of both program coverages. This is the default similarity which works in most cases: Matches with a high average similarity indicate that the programs work in a very similar way.\"},{\"name\":\"MAX\",\"distribution\":[5,1,0,0,0,0,0,0,0,4],\"topComparisons\":[{\"first_submission\":\"A\",\"second_submission\":\"C\",\"similarity\":0.9966329966329966},{\"first_submission\":\"B\",\"second_submission\":\"A\",\"similarity\":0.9766081871345029},{\"first_submission\":\"B\",\"second_submission\":\"C\",\"similarity\":0.9766081871345029},{\"first_submission\":\"D\",\"second_submission\":\"A\",\"similarity\":0.9639751552795031},{\"first_submission\":\"D\",\"second_submission\":\"C\",\"similarity\":0.9639751552795031},{\"first_submission\":\"B\",\"second_submission\":\"D\",\"similarity\":0.8070175438596491},{\"first_submission\":\"E\",\"second_submission\":\"A\",\"similarity\":0.0},{\"first_submission\":\"E\",\"second_submission\":\"D\",\"similarity\":0.0},{\"first_submission\":\"E\",\"second_submission\":\"B\",\"similarity\":0.0},{\"first_submission\":\"E\",\"second_submission\":\"C\",\"similarity\":0.0}],\"description\":\"Maximum of both program coverages. This ranking is especially useful if the programs are very different in size. This can happen when dead code was inserted to disguise the origin of the plagiarized program.\"}],\"clusters\":[]}" - }, - "submissions": { - "A": new Map().set("A\\GSTiling.java","1").set("A\\Match.java","2").set("A\\Matches.java","3").set("A\\Structure.java","4").set("A\\Submission.java","5").set("A\\Table.java","6").set("A\\Token.java","7").set("A\\TokenConstants.java","8"), - "B": new Map().set("B\\Table.java","1").set("B\\Token.java","2").set("B\\TokenConstants.java","3"), - "C": new Map().set("C\\GSTiling.java","1").set("C\\Match.java","2").set("C\\Matches.java","3").set("C\\Structure.java","4").set("C\\Submission.java","5").set("C\\Table.java","6").set("C\\Token.java","7").set("C\\TokenConstants.java","8"), - "D": new Map().set("D\\Match.java","2").set("D\\Matches.java","3").set("D\\Structure.java","4").set("D\\Submission.java","5").set("D\\Table.java","6").set("D\\Token.java","7").set("D\\TokenConstants.java","8"), - "E": new Map().set("E\\WhatAmIDoingHere.java","1"), - }, - "local": false, - "zip": true, - "single": false, - "fileString": "", - "fileIdToDisplayName": new Map().set("A","A").set("B","B").set("C","C").set("D","D").set("E","E") -}); -}) -const json = { - "id1": "B", - "id2": "A", - "similarity": 0.2457689477557027, - "matches": [ - { - "file1": "B\\Table.java", - "file2": "A\\Table.java", - "start1": 5, - "end1": 60, - "start2": 5, - "end2": 60, - "tokens": 92 - }, - { - "file1": "B\\Token.java", - "file2": "A\\Token.java", - "start1": 1, - "end1": 47, - "start2": 1, - "end2": 47, - "tokens": 75 - } - ] -}; - -test("CF", () => { - const comparison = ComparisonFactory.getComparison(json); - expect(comparison.firstSubmissionId).toMatch("B"); - expect(comparison.secondSubmissionId).toMatch("A"); - expect(comparison.similarity).toBe(0.2457689477557027); - expect(comparison.filesOfFirstSubmission.size).toBe(3); - expect(comparison.filesOfSecondSubmission.size).toBe(8); - expect(comparison.colors.length).toBe(2); - expect(comparison.allMatches.length).toBe(2); -}) \ No newline at end of file diff --git a/report-viewer/tests/unit/model/factories/ComparisonFactory.test.ts b/report-viewer/tests/unit/model/factories/ComparisonFactory.test.ts new file mode 100644 index 000000000..1b0a34aab --- /dev/null +++ b/report-viewer/tests/unit/model/factories/ComparisonFactory.test.ts @@ -0,0 +1,74 @@ +import { vi, it, beforeAll, describe, expect } from 'vitest' +import validNew from './ValidNewComparison.json' +import validOld from './ValidOldComparison.json' +import { ComparisonFactory } from '@/model/factories/ComparisonFactory' +import { store } from '@/stores/store' +import { MetricType } from '@/model/MetricType' + +const store = { + state: { + localModeUsed: false, + zipModeUsed: true, + singleModeUsed: false, + files: {} + }, + getComparisonFileName: (id1: string, id2: string) => { + return `${id1}-${id2}.json` + }, + filesOfSubmission: (name: string) => { + return [ + { + name: `${name}/Structure.java`, + value: '' + }, + { + name: `${name}/Submission.java`, + value: '' + } + ] + } +} + +describe('Test JSON to Comparison', () => { + beforeAll(() => { + vi.mock('@/stores/store', () => ({ + store: vi.fn(() => { + return store + }) + })) + }) + + it('Post 5.0', async () => { + store.state.files['root1-root2.json'] = JSON.stringify(validNew) + + const result = await ComparisonFactory.getComparison('root1', 'root2') + + expect(result).toBeDefined() + expect(result.firstSubmissionId).toBe('root1') + expect(result.secondSubmissionId).toBe('root2') + expect(result.similarities[MetricType.AVERAGE]).toBe(0.6900452488687783) + expect(result.similarities[MetricType.MAXIMUM]).toBe(0.9936000000000001) + expect(result.filesOfFirstSubmission).toBeDefined() + expect(result.filesOfSecondSubmission).toBeDefined() + expect(result.allMatches.length).toBe(4) + expect(result.matchesInFirstSubmission.size).toBe(2) + expect(result.matchesInSecondSubmissions.size).toBe(2) + }) + + it('Pre 5.0', async () => { + store.state.files['root1-root2.json'] = JSON.stringify(validOld) + + const result = await ComparisonFactory.getComparison('root1', 'root2') + + expect(result).toBeDefined() + expect(result.firstSubmissionId).toBe('root1') + expect(result.secondSubmissionId).toBe('root2') + expect(result.similarities[MetricType.AVERAGE]).toBe(0.6900452488687783) + expect(result.similarities[MetricType.MAXIMUM]).toBe(Number.NaN) + expect(result.filesOfFirstSubmission).toBeDefined() + expect(result.filesOfSecondSubmission).toBeDefined() + expect(result.allMatches.length).toBe(4) + expect(result.matchesInFirstSubmission.size).toBe(2) + expect(result.matchesInSecondSubmissions.size).toBe(2) + }) +}) diff --git a/report-viewer/tests/unit/model/factories/OverviewFactory.test.ts b/report-viewer/tests/unit/model/factories/OverviewFactory.test.ts new file mode 100644 index 000000000..f2602f3c1 --- /dev/null +++ b/report-viewer/tests/unit/model/factories/OverviewFactory.test.ts @@ -0,0 +1,177 @@ +import { beforeAll, describe, expect, it, vi } from 'vitest' +import { OverviewFactory } from '@/model/factories/OverviewFactory' +import { MetricType } from '@/model/MetricType' +import { HundredValueDistribution } from '@/model/HundredValueDistribution' +import { TenValueDistribution } from '@/model/TenValueDistribution' +import validNew from './ValidNewOverview.json' +import validOld from './ValidOldOverview.json' + +const store = { + state: { + localModeUsed: false, + zipModeUsed: true, + singleModeUsed: false, + files: {} + }, + saveSubmissionNames: (map) => { + expect(map.has('A')).toBeTruthy() + expect(map.has('B')).toBeTruthy() + expect(map.has('C')).toBeTruthy() + expect(map.has('D')).toBeTruthy() + }, + saveComparisonFileLookup: (map) => { + expect(map.has('A')).toBeTruthy() + expect(map.has('B')).toBeTruthy() + } +} + +describe('Test JSON to Overview', () => { + beforeAll(() => { + vi.mock('@/stores/store', () => ({ + store: vi.fn(() => { + return store + }) + })) + + vi.spyOn(global.window, 'alert').mockImplementation(() => {}) + }) + + it('Post 5.0', async () => { + store.state.files['overview.json'] = JSON.stringify(validNew) + + expect(await OverviewFactory.getOverview()).toEqual({ + _submissionFolderPath: ['files'], + _baseCodeFolderPath: '', + _language: 'Javac based AST plugin', + _fileExtensions: ['.java', '.JAVA'], + _matchSensitivity: 9, + _dateOfExecution: '12/07/23', + _durationOfExecution: 12, + _topComparisons: [ + { + firstSubmissionId: 'A', + secondSubmissionId: 'C', + similarities: { + [MetricType.AVERAGE]: 0.9960435212660732, + [MetricType.MAXIMUM]: 0.9960435212660732 + }, + sortingPlace: 0, + id: 1 + }, + { + firstSubmissionId: 'D', + secondSubmissionId: 'A', + similarities: { + [MetricType.AVERAGE]: 0.751044776119403, + [MetricType.MAXIMUM]: 0.947289156626506 + }, + sortingPlace: 1, + id: 2 + }, + { + firstSubmissionId: 'D', + secondSubmissionId: 'C', + similarities: { + [MetricType.AVERAGE]: 0.751044776119403, + [MetricType.MAXIMUM]: 0.947289156626506 + }, + sortingPlace: 2, + id: 3 + }, + { + firstSubmissionId: 'B', + secondSubmissionId: 'D', + similarities: { + [MetricType.AVERAGE]: 0.28322981366459626, + [MetricType.MAXIMUM]: 0.8085106382978723 + }, + sortingPlace: 3, + id: 4 + }, + { + firstSubmissionId: 'B', + secondSubmissionId: 'A', + similarities: { + [MetricType.AVERAGE]: 0.2378472222222222, + [MetricType.MAXIMUM]: 0.9716312056737588 + }, + sortingPlace: 4, + id: 5 + }, + { + firstSubmissionId: 'B', + secondSubmissionId: 'C', + similarities: { + [MetricType.AVERAGE]: 0.2378472222222222, + [MetricType.MAXIMUM]: 0.9716312056737588 + }, + sortingPlace: 5, + id: 6 + } + ], + _distributions: { + [MetricType.MAXIMUM]: new HundredValueDistribution([ + 1, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ]), + [MetricType.AVERAGE]: new HundredValueDistribution([ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ]) + }, + _clusters: [ + { + averageSimilarity: 94.746956, + strength: 0.0, + members: ['C', 'A', 'B', 'D'] + } + ], + _totalComparisons: 6 + }) + }) + + it('Pre 5.0', async () => { + store.state.files['overview.json'] = JSON.stringify(validOld) + expect(await OverviewFactory.getOverview()).toEqual({ + _submissionFolderPath: ['test'], + _baseCodeFolderPath: '', + _language: 'Javac based AST plugin', + _fileExtensions: ['.java', '.JAVA'], + _matchSensitivity: 9, + _dateOfExecution: '12/07/23', + _durationOfExecution: 34, + _topComparisons: [ + { + firstSubmissionId: 'A', + secondSubmissionId: 'B', + similarities: { + [MetricType.AVERAGE]: 0.6900452488687783, + [MetricType.MAXIMUM]: 0.9457364341085271 + }, + sortingPlace: 0, + id: 1 + }, + { + firstSubmissionId: 'C', + secondSubmissionId: 'D', + similarities: { + [MetricType.AVERAGE]: 0.6954045248868778, + [MetricType.MAXIMUM]: 0.83500530023 + }, + sortingPlace: 1, + id: 2 + } + ], + _distributions: { + [MetricType.AVERAGE]: new TenValueDistribution([0, 0, 0, 1, 0, 0, 0, 0, 0, 0]), + [MetricType.MAXIMUM]: new TenValueDistribution([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]) + }, + _clusters: [], + _totalComparisons: 6 + }) + }) +}) diff --git a/report-viewer/tests/unit/model/factories/ValidNewComparison.json b/report-viewer/tests/unit/model/factories/ValidNewComparison.json new file mode 100644 index 000000000..d88d60f40 --- /dev/null +++ b/report-viewer/tests/unit/model/factories/ValidNewComparison.json @@ -0,0 +1,47 @@ +{ + "id1": "root1", + "id2": "root2", + "similarities": { + "AVG": 0.6900452488687783, + "MAX": 0.9936000000000001 + }, + "matches": [ + { + "file1": "root2\\Structure.java", + "file2": "root1\\Structure.java", + "start1": 3, + "end1": 120, + "start2": 1, + "end2": 118, + "tokens": 139 + }, + { + "file1": "root2\\Submission.java", + "file2": "root1\\Submission.java", + "start1": 129, + "end1": 155, + "start2": 134, + "end2": 160, + "tokens": 34 + }, + { + "file1": "root2\\Submission.java", + "file2": "root1\\Submission.java", + "start1": 165, + "end1": 194, + "start2": 173, + "end2": 203, + "tokens": 33 + }, + + { + "file1": "root2\\Submission.java", + "file2": "root1\\Submission.java", + "start1": 112, + "end1": 127, + "start2": 116, + "end2": 132, + "tokens": 23 + } + ] +} diff --git a/report-viewer/tests/unit/model/factories/ValidNewOverview.json b/report-viewer/tests/unit/model/factories/ValidNewOverview.json new file mode 100644 index 000000000..37e23f777 --- /dev/null +++ b/report-viewer/tests/unit/model/factories/ValidNewOverview.json @@ -0,0 +1,73 @@ +{ + "jplag_version": { "major": 0, "minor": 0, "patch": 0 }, + "submission_folder_path": ["files"], + "base_code_folder_path": "", + "language": "Javac based AST plugin", + "file_extensions": [".java", ".JAVA"], + "submission_id_to_display_name": { "A": "A", "B": "B", "C": "C", "D": "D" }, + "submission_ids_to_comparison_file_name": { + "A": { "B": "B-A.json", "C": "A-C.json", "D": "D-A.json" }, + "B": { "A": "B-A.json", "C": "B-C.json", "D": "B-D.json" }, + "C": { "A": "A-C.json", "B": "B-C.json", "D": "D-C.json" }, + "D": { "A": "D-A.json", "B": "B-D.json", "C": "D-C.json" } + }, + "failed_submission_names": [], + "excluded_files": [], + "match_sensitivity": 9, + "date_of_execution": "12/07/23", + "execution_time": 12, + "distributions": { + "MAX": [ + 1, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0 + ], + "AVG": [ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0 + ] + }, + "top_comparisons": [ + { + "first_submission": "A", + "second_submission": "C", + "similarities": { "AVG": 0.9960435212660732, "MAX": 0.9960435212660732 } + }, + { + "first_submission": "D", + "second_submission": "A", + "similarities": { "AVG": 0.751044776119403, "MAX": 0.947289156626506 } + }, + { + "first_submission": "D", + "second_submission": "C", + "similarities": { "AVG": 0.751044776119403, "MAX": 0.947289156626506 } + }, + { + "first_submission": "B", + "second_submission": "D", + "similarities": { "AVG": 0.28322981366459626, "MAX": 0.8085106382978723 } + }, + { + "first_submission": "B", + "second_submission": "A", + "similarities": { "AVG": 0.2378472222222222, "MAX": 0.9716312056737588 } + }, + { + "first_submission": "B", + "second_submission": "C", + "similarities": { "AVG": 0.2378472222222222, "MAX": 0.9716312056737588 } + } + ], + "clusters": [ + { + "average_similarity": 94.746956, + "strength": 0.0, + "members": ["C", "A", "B", "D"] + } + ], + "total_comparisons": 6 +} diff --git a/report-viewer/tests/unit/model/factories/ValidOldComparison.json b/report-viewer/tests/unit/model/factories/ValidOldComparison.json new file mode 100644 index 000000000..51606b4b5 --- /dev/null +++ b/report-viewer/tests/unit/model/factories/ValidOldComparison.json @@ -0,0 +1,44 @@ +{ + "id1": "root1", + "id2": "root2", + "similarity": 0.6900452488687783, + "matches": [ + { + "file1": "root2\\Structure.java", + "file2": "root1\\Structure.java", + "start1": 3, + "end1": 120, + "start2": 1, + "end2": 118, + "tokens": 139 + }, + { + "file1": "root2\\Submission.java", + "file2": "root1\\Submission.java", + "start1": 129, + "end1": 155, + "start2": 134, + "end2": 160, + "tokens": 34 + }, + { + "file1": "root2\\Submission.java", + "file2": "root1\\Submission.java", + "start1": 165, + "end1": 194, + "start2": 173, + "end2": 203, + "tokens": 33 + }, + + { + "file1": "root2\\Submission.java", + "file2": "root1\\Submission.java", + "start1": 112, + "end1": 127, + "start2": 116, + "end2": 132, + "tokens": 23 + } + ] +} diff --git a/report-viewer/tests/unit/model/factories/ValidOldOverview.json b/report-viewer/tests/unit/model/factories/ValidOldOverview.json new file mode 100644 index 000000000..7f3ea409a --- /dev/null +++ b/report-viewer/tests/unit/model/factories/ValidOldOverview.json @@ -0,0 +1,55 @@ +{ + "jplag_version": { "major": 4, "minor": 2, "patch": 0 }, + "submission_folder_path": ["test"], + "base_code_folder_path": "", + "language": "Javac based AST plugin", + "file_extensions": [".java", ".JAVA"], + "submission_id_to_display_name": { "A": "A", "B": "B", "C": "C", "D": "D" }, + "submission_ids_to_comparison_file_name": { + "A": { "B": "B-A.json" }, + "B": { "A": "B-A.json" } + }, + "failed_submission_names": [], + "excluded_files": [], + "match_sensitivity": 9, + "date_of_execution": "12/07/23", + "execution_time": 34, + "metrics": [ + { + "name": "AVG", + "distribution": [0, 0, 0, 1, 0, 0, 0, 0, 0, 0], + "topComparisons": [ + { + "first_submission": "A", + "second_submission": "B", + "similarity": 0.6900452488687783 + }, + { + "first_submission": "C", + "second_submission": "D", + "similarity": 0.6954045248868778 + } + ], + "description": "Average of both program coverages. This is the default similarity which works in most cases: Matches with a high average similarity indicate that the programs work in a very similar way." + }, + { + "name": "MAX", + "distribution": [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "topComparisons": [ + { + "first_submission": "A", + "second_submission": "B", + "similarity": 0.9457364341085271 + }, + { + "first_submission": "C", + "second_submission": "D", + "similarity": 0.83500530023 + } + ], + "description": "Maximum of both program coverages. This ranking is especially useful if the programs are very different in size. This can happen when dead code was inserted to disguise the origin of the plagiarized program." + } + ], + "clusters": [], + "total_comparisons": 6 +} diff --git a/report-viewer/tsconfig.app.json b/report-viewer/tsconfig.app.json new file mode 100644 index 000000000..342a91072 --- /dev/null +++ b/report-viewer/tsconfig.app.json @@ -0,0 +1,12 @@ +{ + "extends": ["@vue/tsconfig/tsconfig.dom.json", "./tsconfig.module.json"], + "include": ["env.d.ts", "src/**/*", "src/**/*.vue", "src/**/*.json"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/report-viewer/tsconfig.json b/report-viewer/tsconfig.json index 89a8debf3..9497e9a50 100644 --- a/report-viewer/tsconfig.json +++ b/report-viewer/tsconfig.json @@ -1,41 +1,17 @@ { "compilerOptions": { - "target": "esnext", - "module": "esnext", - "strict": true, - "jsx": "preserve", - "importHelpers": true, - "moduleResolution": "node", - "skipLibCheck": true, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "baseUrl": ".", - "types": [ - "webpack-env", - "jest" - ], - "paths": { - "@/*": [ - "src/*" - ] - }, - "lib": [ - "esnext", - "dom", - "dom.iterable", - "scripthost" - ], - "resolveJsonModule": true, + "resolveJsonModule": true }, - "include": [ - "src/**/*.ts", - "src/**/*.tsx", - "src/**/*.vue", - "tests/**/*.ts", - "tests/**/*.tsx" - ], - "exclude": [ - "node_modules" + "files": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + }, + { + "path": "./tsconfig.node.json" + } ] } diff --git a/report-viewer/tsconfig.module.json b/report-viewer/tsconfig.module.json new file mode 100644 index 000000000..7b8d34ff3 --- /dev/null +++ b/report-viewer/tsconfig.module.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "moduleResolution": "Node" + } +} diff --git a/report-viewer/tsconfig.node.json b/report-viewer/tsconfig.node.json new file mode 100644 index 000000000..6ad518e1b --- /dev/null +++ b/report-viewer/tsconfig.node.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.module.json", + "include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "playwright.config.*"], + "compilerOptions": { + "composite": true, + "types": ["node"] + } +} diff --git a/report-viewer/tsconfig.vitest.json b/report-viewer/tsconfig.vitest.json new file mode 100644 index 000000000..d080d611e --- /dev/null +++ b/report-viewer/tsconfig.vitest.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/report-viewer/vite.config.ts b/report-viewer/vite.config.ts new file mode 100644 index 000000000..96fc3d2f2 --- /dev/null +++ b/report-viewer/vite.config.ts @@ -0,0 +1,27 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import type { UserConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig((userConfig: UserConfig) => { + let base = '/' + switch (userConfig.mode) { + case 'dev': + base = '/JPlag-Dev/' + break + case 'prod': + base = '/JPlag/' + break + } + return { + plugins: [vue()], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + }, + base: base + } +}) diff --git a/report-viewer/vitest.config.ts b/report-viewer/vitest.config.ts new file mode 100644 index 000000000..95b5260d9 --- /dev/null +++ b/report-viewer/vitest.config.ts @@ -0,0 +1,17 @@ +import { fileURLToPath } from 'node:url' +import { configDefaults, defineConfig } from 'vitest/config' +import vue from '@vitejs/plugin-vue' + +export default defineConfig({ + plugins: [vue()], + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'tests/e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + }, + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/report-viewer/vue.config.js b/report-viewer/vue.config.js deleted file mode 100644 index af4cb1dbd..000000000 --- a/report-viewer/vue.config.js +++ /dev/null @@ -1,15 +0,0 @@ -const { defineConfig } = require("@vue/cli-service"); -const NodePolyfillPlugin = require("node-polyfill-webpack-plugin"); -module.exports = defineConfig({ - publicPath: '', - transpileDependencies: true, - configureWebpack: { - plugins: [new NodePolyfillPlugin()], - optimization: { - splitChunks: { - chunks: "all", - }, - }, - devtool: 'source-map' - }, -});