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/files/progpedia.zip b/.github/workflows/files/progpedia.zip new file mode 100644 index 000000000..7af75298c Binary files /dev/null and b/.github/workflows/files/progpedia.zip differ diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index a9ec43e97..e83f58f23 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -1,10 +1,20 @@ name: Build on: - push: + 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,24 +36,28 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: - java-version: 17 + java-version: 21 distribution: 'temurin' - + + - uses: actions/setup-node@v4 + with: + node-version: "18" + - name: Run Tests run: mvn verify -B -U - + - name: Build Assembly - run: mvn clean package assembly:single - + run: mvn -Pwith-report-viewer clean package assembly:single + - name: Upload Assembly - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: "JPlag" path: "jplag.cli/target/jplag-*-jar-with-dependencies.jar" - + diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index ca224e041..b4ea875e3 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -7,17 +7,17 @@ jobs: publish-maven-central: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: - java-version: '17' + java-version: '21' distribution: 'temurin' - name: Set maven settings.xml - uses: whelk-io/maven-settings-xml-action@v21 + uses: whelk-io/maven-settings-xml-action@v22 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,13 +29,17 @@ jobs: publish-release-artifact: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: - java-version: '17' + java-version: '21' distribution: 'temurin' + - uses: actions/setup-node@v4 + with: + node-version: "18" + - name: Build JPlag - run: mvn -U -B clean package assembly:single + run: mvn -Pwith-report-viewer -U -B clean package assembly:single - name: Attach CLI to Release on GitHub uses: softprops/action-gh-release@v1 diff --git a/.github/workflows/report-viewer-test.yml b/.github/workflows/report-viewer-build-test.yml similarity index 88% rename from .github/workflows/report-viewer-test.yml rename to .github/workflows/report-viewer-build-test.yml index 3093d2457..5958c26ad 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 + - uses: actions/setup-node@v4 with: - node-version: "16" + node-version: "18" - name: Set version of Report Viewer shell: bash diff --git a/.github/workflows/report-viewer-demo.yml b/.github/workflows/report-viewer-demo.yml new file mode 100644 index 000000000..78e6fbe37 --- /dev/null +++ b/.github/workflows/report-viewer-demo.yml @@ -0,0 +1,113 @@ +name: Report Viewer Demo Deployment + +on: + workflow_dispatch: # Use this to dispatch from the Actions Tab + push: + branches: + - main + +jobs: + build-jar: + runs-on: ubuntu-latest + + steps: + - name: Checkout ๐Ÿ›Ž๏ธ + uses: actions/checkout@v4 + + - name: Set up JDK + uses: actions/setup-java@v4 + with: + java-version: 21 + distribution: 'temurin' + + - name: Build Assembly + run: mvn clean package assembly:single + + - name: Upload Assembly + uses: actions/upload-artifact@v4 + with: + name: "JPlag" + path: "cli/target/jplag-*-jar-with-dependencies.jar" + + + run-example: + needs: build-jar + runs-on: ubuntu-latest + + steps: + - name: Checkout ๐Ÿ›Ž๏ธ + uses: actions/checkout@v4 + + - name: Set up JDK + uses: actions/setup-java@v4 + with: + java-version: 21 + distribution: 'temurin' + + - name: Get JAR + uses: actions/download-artifact@v4 + with: + name: JPlag + + - name: Copy and unzip submissions + run: unzip ./.github/workflows/files/progpedia.zip + + - name: Rename jar + run: mv *.jar ./jplag.jar + + - name: Run JPlag + run: java -jar jplag.jar ACCEPTED -bc base -r example + + - name: Upload Result + uses: actions/upload-artifact@v4 + with: + name: "Result" + path: "example.zip" + + + build-and-deploy: + needs: run-example + runs-on: ubuntu-latest + steps: + - name: Checkout ๐Ÿ›Ž๏ธ + uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: "18" + + - name: Set version of Report Viewer + shell: bash + run: | + VERSION=$(grep "" pom.xml | grep -oPm1 "(?<=)[^-|<]+") + MAJOR=$(echo $VERSION | cut -d '.' -f 1) + MINOR=$(echo $VERSION | cut -d '.' -f 2) + PATCH=$(echo $VERSION | cut -d '.' -f 3) + json=$(cat report-viewer/src/version.json) + json=$(echo "$json" | jq --arg MAJOR "$MAJOR" --arg MINOR "$MINOR" --arg PATCH "$PATCH" '.report_viewer_version |= { "major": $MAJOR | tonumber, "minor": $MINOR | tonumber, "patch": $PATCH | tonumber }') + echo "$json" > report-viewer/src/version.json + echo "Version of Report Viewer:" + cat report-viewer/src/version.json + + - name: Download Results + uses: actions/download-artifact@v4 + with: + name: Result + path: report-viewer/public + + - name: Install and Build ๐Ÿ”ง + working-directory: report-viewer + run: | + npm install + npm run build-demo + + - name: Deploy ๐Ÿš€ + uses: JamesIves/github-pages-deploy-action@v4.5.0 + with: + branch: gh-pages + folder: report-viewer/dist + repository-name: JPlag/Demo + token: ${{ secrets.SDQ_DEV_DEPLOY_TOKEN }} + clean: true + single-commit: true + diff --git a/.github/workflows/report-viewer-dev.yml b/.github/workflows/report-viewer-dev.yml index a17775f7f..2f849fb6a 100644 --- a/.github/workflows/report-viewer-dev.yml +++ b/.github/workflows/report-viewer-dev.yml @@ -5,39 +5,29 @@ 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 + - uses: actions/setup-node@v4 with: - node-version: "16" - - - name: Set version of Report Viewer - shell: bash - run: | - VERSION=$(grep "" pom.xml | grep -oPm1 "(?<=)[^-|<]+") - MAJOR=$(echo $VERSION | cut -d '.' -f 1) - MINOR=$(echo $VERSION | cut -d '.' -f 2) - PATCH=$(echo $VERSION | cut -d '.' -f 3) - sed -i "/major/s/.*/ \"major\": $MAJOR,/" report-viewer/src/version.json - sed -i "/minor/s/.*/ \"minor\": $MINOR,/" report-viewer/src/version.json - sed -i "/patch/s/.*/ \"patch\": $PATCH/" report-viewer/src/version.json - echo "Version of Report Viewer:" - cat report-viewer/src/version.json + node-version: "18" - name: Install and Build ๐Ÿ”ง 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.5.0 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..98744e554 --- /dev/null +++ b/.github/workflows/report-viewer-e2e.yml @@ -0,0 +1,58 @@ +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@v4 + with: + node-version: "18" + + - name: Install and Build ๐Ÿ”ง + working-directory: report-viewer + run: | + npm install + npm run build + + - name: Install playwright ๐Ÿ”ง + working-directory: report-viewer + run: npx playwright install --with-deps + + - name: Run tests ๐Ÿงช + working-directory: report-viewer + run: | + npm run test:e2e + + - name: Upload test results ๐Ÿ“ค + uses: actions/upload-artifact@v4 + if: always() + with: + name: test-results + path: | + report-viewer/test-results + report-viewer/playwright-report + retention-days: 30 \ 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..080b1a02f --- /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@v4 + 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..eb1cc46e3 --- /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@v4 + 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..3a0738588 --- /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@v4 + 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..f1662be72 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 + - uses: actions/setup-node@v4 with: - node-version: "16" + node-version: "18" - name: Set version of Report Viewer shell: bash @@ -24,9 +24,9 @@ jobs: MAJOR=$(echo $VERSION | cut -d '.' -f 1) MINOR=$(echo $VERSION | cut -d '.' -f 2) PATCH=$(echo $VERSION | cut -d '.' -f 3) - sed -i "/major/s/.*/ \"major\": $MAJOR,/" report-viewer/src/version.json - sed -i "/minor/s/.*/ \"minor\": $MINOR,/" report-viewer/src/version.json - sed -i "/patch/s/.*/ \"patch\": $PATCH/" report-viewer/src/version.json + json=$(cat report-viewer/src/version.json) + json=$(echo "$json" | jq --arg MAJOR "$MAJOR" --arg MINOR "$MINOR" --arg PATCH "$PATCH" '.report_viewer_version |= { "major": $MAJOR | tonumber, "minor": $MINOR | tonumber, "patch": $PATCH | tonumber }') + echo "$json" > report-viewer/src/version.json echo "Version of Report Viewer:" cat report-viewer/src/version.json @@ -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.5.0 with: branch: gh-pages folder: report-viewer/dist diff --git a/.github/workflows/sonarcloud-branch.yml b/.github/workflows/sonarcloud-branch.yml index 93c743268..486fb0777 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,28 +21,28 @@ 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 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'temurin' - java-version: 17 + java-version: 21 - name: Cache SonarCloud packages - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar - name: Cache Maven packages - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.m2 key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} restore-keys: ${{ runner.os }}-m2 - + - name: Build and analyze env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/sonarcloud-pr.yml b/.github/workflows/sonarcloud-pr.yml index 360b37dd7..5c3cfc300 100644 --- a/.github/workflows/sonarcloud-pr.yml +++ b/.github/workflows/sonarcloud-pr.yml @@ -42,30 +42,30 @@ 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 }} fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - name: Set up JDK - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'temurin' - java-version: 17 + java-version: 21 - name: Cache SonarCloud packages - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar - name: Cache Maven packages - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.m2 key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} restore-keys: ${{ runner.os }}-m2 - + - name: Build and analyze (PR) env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/spotless.yml b/.github/workflows/spotless.yml index a920d8faf..51058bb69 100644 --- a/.github/workflows/spotless.yml +++ b/.github/workflows/spotless.yml @@ -1,10 +1,20 @@ 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,16 +36,16 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: - java-version: 17 + java-version: 21 distribution: 'temurin' - + - name: Check with Spotless run: mvn clean spotless:check - - + + 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..303ce1a57 100644 --- a/README.md +++ b/README.md @@ -8,35 +8,48 @@ [![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) +[![Java Version](https://img.shields.io/badge/java-SE%2021-yellowgreen)](#download-and-installation) -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 currently supports various programming languages, EMF metamodels, and natural language text. +JPlag finds pairwise similarities among a set of multiple programs. It can reliably detect software plagiarism and collusion in software development, even when obfuscated. All similarities are calculated locally, and no source code or plagiarism results are ever uploaded to the internet. JPlag supports a large number of programming and modeling languages. + +* ๐Ÿ“ˆ [JPlag Demo](https://jplag.github.io/Demo/) + +* ๐Ÿ›๏ธ [JPlag on Helmholtz RSD](https://helmholtz.software/software/jplag) + +* ๐Ÿคฉ [Give us Feedback in a **short (<5 min) survey**](https://docs.google.com/forms/d/e/1FAIpQLSckqUlXhIlJ-H2jtu2VmGf_mJt4hcnHXaDlwhpUL3XG1I8UYw/viewform?usp=sf_link) + ## 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 | +All supported languages and their supported versions are listed below. + +| Language | Version | CLI Argument Name | [state](https://github.com/jplag/JPlag/wiki/2.-Supported-Languages) | parser | +|--------------------------------------------------------|---------------------------------------------------------------------------------------:|-------------------|:-------------------------------------------------------------------:|:---------:| +| [Java](https://www.java.com) | 21 | java | mature | JavaC | +| [C](https://isocpp.org) | 11 | c | legacy | JavaCC | +| [C++](https://isocpp.org) | 14 | cpp | beta | ANTLR 4 | +| [C#](https://docs.microsoft.com/en-us/dotnet/csharp/) | 6 | csharp | mature | ANTLR 4 | +| [Python](https://www.python.org) | 3.6 | python3 | legacy | ANTLR 4 | +| [JavaScript](https://www.javascript.com/) | ES6 | javascript | beta | ANTLR 4 | +| [TypeScript](https://www.typescriptlang.org/) | [~5](https://github.com/antlr/grammars-v4/tree/master/javascript/typescript/README.md) | typescript | beta | ANTLR 4 | +| [Go](https://go.dev) | 1.17 | golang | beta | ANTLR 4 | +| [Kotlin](https://kotlinlang.org) | 1.3 | kotlin | beta | 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 | +| [Swift](https://www.swift.org) | 5.4 | swift | beta | ANTLR 4 | +| [Scala](https://www.scala-lang.org) | 2.13.8 | scala | beta | Scalameta | +| [LLVM IR](https://llvm.org) | 15 | llvmir | beta | ANTLR 4 | +| [Scheme](http://www.scheme-reports.org) | ? | scheme | legacy | JavaCC | +| [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 | +| [SCXML](https://www.w3.org/TR/scxml/) | 1.0 | scxml | alpha | XML | +| Text (naive) | - | text | legacy | CoreNLP | ## Download and Installation -You need Java SE 17 to run or build JPlag. +You need Java SE 21 to run or build JPlag. ### Downloading a release * Download a [released version](https://github.com/jplag/jplag/releases). @@ -48,6 +61,7 @@ JPlag is released on [Maven Central](https://search.maven.org/search?q=de.jplag) de.jplag jplag + ``` @@ -55,51 +69,87 @@ JPlag is released on [Maven Central](https://search.maven.org/search?q=de.jplag) 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 `cli/target`. + Run `mvn -P with-report-viewer clean package assembly:single` to build the full jar with the report viewer. In this case, you'll need [Node.js](https://nodejs.org/en/download) installed. +3. You will find the generated JARs in the subdirectory `cli/target`. ## Usage JPlag can either be used via the CLI or directly via its Java API. For more information, see the [usage information in the wiki](https://github.com/jplag/JPlag/wiki/1.-How-to-Use-JPlag). If you are using the CLI, you can display your results via [jplag.github.io](https://jplag.github.io/JPlag/). No data will leave your computer! ### 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 (`jplag [jplag options] [language options]`). A subcommand takes priority over the -l option. +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 - 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) +Parameter descriptions: + [root-dirs[,root-dirs...]...] + Root-directory with submissions to check for plagiarism. + -bc, --bc, --base-code= + Path to the base code directory (common framework used in all submissions). + -l, --language= + Select the language of the submissions (default: java). See subcommands below. + -M, --mode=<{RUN, VIEW, RUN_AND_VIEW}> + The mode of JPlag: either only run analysis, only open the viewer, or do both (default: null) + -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: 500) + -new, --new=[,...] + Root-directories with submissions to check for plagiarism (same as root). + --normalize Activate the normalization of tokens. Supported for languages: Java, C++. + -old, --old=[,...] + Root-directories with prior submissions to compare against. + -r, --result-file= + Name of the file in which the comparison results will be stored (default: results). Missing .zip endings will be automatically added. + -t, --min-tokens= + Tunes the comparison sensitivity by adjusting the minimum token required to be counted as a matching section. A smaller value increases the sensitivity but might lead to more + false-positives. + +Advanced + --csv-export Export pairwise similarity values as a CSV file. + -d, --debug Store on-parsable files in error folder. + -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. + -P, --port= The port used for the internal report viewer (default: 1996). + -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=<{AGGLOMERATIVE, SPECTRAL}> + Specifies the clustering algorithm (default: spectral). + --cluster-metric=<{AVG, MIN, MAX, INTERSECTION}> + The similarity metric used for clustering (default: average similarity). + --cluster-skip Skips the cluster calculation. + +Subsequence Match Merging + --gap-size= + Maximal gap between neighboring matches to be merged (between 1 and minTokenMatch, default: 6). + --match-merging Enables merging of neighboring matches to counteract obfuscation attempts. + --neighbor-length= + Minimal length of neighboring matches to be merged (between 1 and minTokenMatch, default: 2). + +Subcommands (supported languages): + c + cpp + csharp + emf + emf-model + go + java + javascript + kotlin + llvmir + python3 + rlang + rust + scala + scheme + scxml + swift + text + typescript ``` ### Java API @@ -109,20 +159,21 @@ The new API makes it easy to integrate JPlag's plagiarism detection into externa ```java -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(); - reportObjectFactory.createAndSaveReport(result, "/path/to/output"); + ReportObjectFactory reportObjectFactory = new ReportObjectFactory(new File("/path/to/output")); + reportObjectFactory.createAndSaveReport(result); } catch (ExitException e) { // error handling here +} catch (FileNotFoundException e) { + // handle IO exception here } ``` diff --git a/cli/pom.xml b/cli/pom.xml index 56acda2d0..c676605e7 100644 --- a/cli/pom.xml +++ b/cli/pom.xml @@ -7,6 +7,7 @@ ${revision} cli + @@ -49,12 +50,12 @@ de.jplag - cpp + c ${revision} de.jplag - cpp2 + cpp ${revision} @@ -87,6 +88,11 @@ scheme ${revision} + + de.jplag + scxml + ${revision} + de.jplag swift @@ -97,6 +103,26 @@ emf-metamodel ${revision} + + de.jplag + emf-model + ${revision} + + + de.jplag + typescript + ${revision} + + + de.jplag + javascript + ${revision} + + + de.jplag + llvmir + ${revision} + org.kohsuke.metainf-services @@ -104,8 +130,15 @@ - net.sourceforge.argparse4j - argparse4j + info.picocli + picocli + 4.7.5 + + + + me.tongfei + progressbar + 0.10.0 @@ -140,4 +173,56 @@ + + + + with-report-viewer + + + + report-viewer + ../report-viewer/dist + + + + + org.codehaus.mojo + exec-maven-plugin + 1.3.2 + + + npm install + + exec + + generate-resources + + npm + ../report-viewer + + install + + + + + npm build + + exec + + generate-resources + + npm + ../report-viewer + + run + build + + + + + + + + + diff --git a/cli/src/main/java/de/jplag/cli/CLI.java b/cli/src/main/java/de/jplag/cli/CLI.java index 3694b474e..ac79e68c0 100644 --- a/cli/src/main/java/de/jplag/cli/CLI.java +++ b/cli/src/main/java/de/jplag/cli/CLI.java @@ -1,39 +1,20 @@ 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.awt.Desktop; import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.URI; 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 +23,24 @@ import de.jplag.JPlag; import de.jplag.JPlagResult; +import de.jplag.Language; import de.jplag.cli.logger.CollectedLoggerFactory; +import de.jplag.cli.logger.TongfeiProgressBarProvider; +import de.jplag.cli.server.ReportViewer; import de.jplag.clustering.ClusteringOptions; import de.jplag.clustering.Preprocessing; import de.jplag.exceptions.ExitException; +import de.jplag.logging.ProgressBarLogger; +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. @@ -64,17 +52,25 @@ public final class CLI { 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 CREDITS = "Created by IPD Tichy, Guido Malpohl, and others. Maintained by Timur Saglam and Sebastian Hahner. Logo by Sandro Koch."; 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.", "State of the Art Obfuscation Resilience", "www.helmholtz.software/software/jplag"}; - 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 UNKOWN_LANGAUGE_EXCEPTION = "Language %s does not exists. Available languages are: %s"; + + private static final String DESCRIPTION_PATTERN = "%nJPlag - %s%n%s%n%n"; + + private static final String DEFAULT_FILE_ENDING = ".zip"; /** * Main class for using JPlag via the CLI. @@ -83,153 +79,220 @@ 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())); - } catch (ExitException exception) { - logger.error(exception.getMessage()); // do not pass exception here to keep log clean + + ParseResult parseResult = cli.parseOptions(args); + + if (!parseResult.isUsageHelpRequested() && !(parseResult.subcommand() != null && parseResult.subcommand().isUsageHelpRequested())) { + ProgressBarLogger.setProgressBarProvider(new TongfeiProgressBarProvider()); + switch (cli.options.mode) { + case RUN -> cli.runJPlag(parseResult); + case VIEW -> cli.runViewer(null); + case RUN_AND_VIEW -> cli.runViewer(cli.runJPlag(parseResult)); + } + } + } catch (ExitException | IOException exception) { // do not pass exceptions here to keep log clean + if (exception.getCause() != null) { + logger.error("{} - {}", exception.getMessage(), exception.getCause().getMessage()); + } else { + logger.error(exception.getMessage()); + } + finalizeLogger(); System.exit(1); } } - 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; + } + 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); + } + + public File runJPlag(ParseResult parseResult) throws ExitException, FileNotFoundException { + JPlagOptions jplagOptions = buildOptionsFromArguments(parseResult); + JPlagResult result = JPlag.run(jplagOptions); + File target = new File(getResultFilePath()); + ReportObjectFactory reportObjectFactory = new ReportObjectFactory(target); + reportObjectFactory.createAndSaveReport(result); + logger.info("Successfully written the result: {}", target.getPath()); + logger.info("View the result using --mode or at: https://jplag.github.io/JPlag/"); + OutputFileGenerator.generateCsvOutput(result, new File(getResultFileBaseName()), this.options); + return target; + } + + public void runViewer(File zipFile) throws IOException { + ReportViewer reportViewer = new ReportViewer(zipFile, this.options.advanced.port); + int port = reportViewer.start(); + logger.info("ReportViewer started on port http://localhost:{}", port); + Desktop.getDesktop().browse(URI.create("http://localhost:" + port + "/")); + + System.out.println("Press Enter key to exit..."); + System.in.read(); + reportViewer.stop(); + } + + 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.ParameterException e) { + if (e.getArgSpec() != null && e.getArgSpec().isOption() && Arrays.asList(((OptionSpec) e.getArgSpec()).names()).contains("-l")) { + throw new CliException(String.format(UNKOWN_LANGAUGE_EXCEPTION, e.getValue(), + String.join(", ", LanguageLoader.getAllAvailableLanguageIdentifiers()))); + } + throw new CliException("Error during parsing", e); + } 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; } - return null; + 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, this.options.normalize); - 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); - } else { - logger.warn("Using legacy partial base code API. Please migrate to new full path base code API."); - return options.withBaseCodeSubmissionName(baseCodePath); + return jPlagOptions.withBaseCodeSubmissionDirectory(baseCodeDirectory); } + logger.warn("Using legacy partial base code API. Please migrate to new full path base code API."); + 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)); + private Language loadLanguage(ParseResult result) throws CliException { + if (result.subcommand() == null) { + return this.options.language; } - 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)); - } - if (CLUSTER_PREPROCESSING_NONE.isSet(namespace) && Boolean.TRUE.equals(CLUSTER_PREPROCESSING_NONE.getFrom(namespace))) { + 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; + } + + 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; + private String getResultFilePath() { + String optionValue = this.options.resultFile; + if (optionValue.endsWith(DEFAULT_FILE_ENDING)) { + return optionValue; } - argumentValues.forEach(destinationRootDirectories::addAll); + return optionValue + DEFAULT_FILE_ENDING; + } + + private String getResultFileBaseName() { + String defaultOutputFile = getResultFilePath(); + return defaultOutputFile.substring(0, defaultOutputFile.length() - DEFAULT_FILE_ENDING.length()); } } 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..384a2d41c --- /dev/null +++ b/cli/src/main/java/de/jplag/cli/CliOptions.java @@ -0,0 +1,166 @@ +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.merging.MergingOptions; +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.", split = ",") + public File[] rootDirectory = new File[0]; + + @Option(names = {"--new", "-new"}, split = ",", description = "Root-directories with submissions to check for plagiarism (same as root).") + public File[] newDirectories = new File[0]; + + @Option(names = {"--old", "-old"}, split = ",", description = "Root-directories with prior submissions to compare against.") + public File[] oldDirectories = new File[0]; + + @Option(names = {"--language", + "-l"}, arity = "1", converter = LanguageConverter.class, completionCandidates = LanguageCandidates.class, description = "Select the language of the submissions (default: ${DEFAULT-VALUE}). See subcommands below.") + public Language language = defaultLanguage; + + @Option(names = {"-bc", "--bc", "--base-code"}, description = "Path to the base code directory (common framework used in all submissions).") + 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 value increases the sensitivity but might lead to more false-positives.") + public Integer minTokenMatch = null; + + @Option(names = {"-h", "--help"}, usageHelp = true, description = "Display this help text", hidden = true) + 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: ${DEFAULT-VALUE})") + public int shownComparisons = JPlagOptions.DEFAULT_SHOWN_COMPARISONS; + + @Option(names = {"-r", + "--result-file"}, description = "Name of the file in which the comparison results will be stored (default: ${DEFAULT-VALUE}). Missing .zip endings will be automatically added.") + public String resultFile = "results"; + + @Option(names = {"-M", + "--mode"}, description = "The mode of JPlag: either only run analysis, only open the viewer, or do both (default: ${DEFAULT_VALUE})") + public JPlagMode mode = JPlagMode.RUN; + + @Option(names = {"--normalize"}, description = "Activate the normalization of tokens. Supported for languages: Java, C++.") + public boolean normalize = false; + + @ArgGroup(heading = "%nAdvanced%n", exclusive = false) + public Advanced advanced = new Advanced(); + + @ArgGroup(validate = false, heading = "%nClustering%n") + public Clustering clustering = new Clustering(); + + @ArgGroup(validate = false, heading = "%nSubsequence Match Merging%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 = "Store on-parsable files in error folder.") + public boolean debug; + + @Option(names = {"-s", "--subdirectory"}, description = "Look in directories /*/ for programs.") + public String subdirectory; + + @Option(names = {"-p", "--suffixes"}, split = ",", description = "comma-separated list of all filename suffixes that are included.") + 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).") + 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: ${DEFAULT-VALUE}).") + public double similarityThreshold = JPlagOptions.DEFAULT_SIMILARITY_THRESHOLD; + + @Option(names = {"-P", "--port"}, description = "The port used for the internal report viewer (default: ${DEFAULT-VALUE}).") + public int port = 1996; + + @Option(names = "--csv-export", description = "Export pairwise similarity values as a CSV file.") + public boolean csvExport = false; + } + + public static class Clustering { + @Option(names = {"--cluster-skip"}, description = "Skips the cluster calculation.") + public boolean disable; + + @ArgGroup + public ClusteringEnabled enabled = new ClusteringEnabled(); + + public static class ClusteringEnabled { + @Option(names = {"--cluster-alg", "--cluster-algorithm"}, description = "Specifies the clustering algorithm (default: ${DEFAULT-VALUE}).") + public ClusteringAlgorithm algorithm = new ClusteringOptions().algorithm(); + + @Option(names = {"--cluster-metric"}, description = "The similarity metric used for clustering (default: ${DEFAULT-VALUE}).") + public SimilarityMetric metric = new ClusteringOptions().similarityMetric(); + } + } + + public static class Merging { + @Option(names = {"--match-merging"}, description = "Enables merging of neighboring matches to counteract obfuscation attempts.") + public boolean enabled = MergingOptions.DEFAULT_ENABLED; + + @Option(names = { + "--neighbor-length"}, description = "Minimal length of neighboring matches to be merged (between 1 and minTokenMatch, default: ${DEFAULT-VALUE}).%n") + public int minimumNeighborLength = MergingOptions.DEFAULT_NEIGHBOR_LENGTH; + + @Option(names = { + "--gap-size"}, description = "Maximal gap between neighboring matches to be merged (between 1 and minTokenMatch, default: ${DEFAULT-VALUE}).") + public int maximumGapSize = MergingOptions.DEFAULT_GAP_SIZE; + + } + + @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/JPlagMode.java b/cli/src/main/java/de/jplag/cli/JPlagMode.java new file mode 100644 index 000000000..402a18b58 --- /dev/null +++ b/cli/src/main/java/de/jplag/cli/JPlagMode.java @@ -0,0 +1,19 @@ +package de.jplag.cli; + +/** + * The mode JPlag runs in. This influences which steps JPlag will execute. + */ +public enum JPlagMode { + /** + * Only run JPlag and create a results.zip + */ + RUN, + /** + * Only start the report viewer + */ + VIEW, + /** + * Run JPlag and open the result in report viewer + */ + RUN_AND_VIEW +} 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/LanguageLoader.java b/cli/src/main/java/de/jplag/cli/LanguageLoader.java index 77c2de673..2ee1c815b 100644 --- a/cli/src/main/java/de/jplag/cli/LanguageLoader.java +++ b/cli/src/main/java/de/jplag/cli/LanguageLoader.java @@ -32,8 +32,9 @@ private LanguageLoader() { * @return the languages as unmodifiable map from identifier to language instance. */ public static synchronized Map getAllAvailableLanguages() { - if (cachedLanguageInstances != null) + if (cachedLanguageInstances != null) { return cachedLanguageInstances; + } Map languages = new TreeMap<>(); @@ -44,10 +45,10 @@ public static synchronized Map getAllAvailableLanguages() { languages.remove(languageIdentifier); continue; } - logger.debug("Loading Language Module '{}'", language.getName()); + logger.trace("Loading Language Module '{}'", language.getName()); languages.put(languageIdentifier, language); } - logger.info("Available languages: '{}'", languages.values().stream().map(Language::getName).toList()); + logger.debug("Available languages: '{}'", languages.values().stream().map(Language::getName).toList()); cachedLanguageInstances = Collections.unmodifiableMap(languages); return cachedLanguageInstances; @@ -61,8 +62,9 @@ public static synchronized Map getAllAvailableLanguages() { */ public static Optional getLanguage(String identifier) { var language = getAllAvailableLanguages().get(identifier); - if (language == null) + if (language == null) { logger.warn("Attempt to load Language {} was not successful", identifier); + } return Optional.ofNullable(language); } diff --git a/cli/src/main/java/de/jplag/cli/OutputFileGenerator.java b/cli/src/main/java/de/jplag/cli/OutputFileGenerator.java new file mode 100644 index 000000000..028361346 --- /dev/null +++ b/cli/src/main/java/de/jplag/cli/OutputFileGenerator.java @@ -0,0 +1,36 @@ +package de.jplag.cli; + +import java.io.File; +import java.io.IOException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import de.jplag.JPlagResult; +import de.jplag.csv.comparisons.CsvComparisonOutput; + +public final class OutputFileGenerator { + private static final Logger logger = LoggerFactory.getLogger(OutputFileGenerator.class); + + private OutputFileGenerator() { + // Prevents default constructor + } + + /** + * Exports the given result as csvs, if the csvExport is activated in the options. Both a full and an anonymized version + * will be written. + * @param result The result to export + * @param outputRoot The root folder for the output + * @param options The cli options + */ + public static void generateCsvOutput(JPlagResult result, File outputRoot, CliOptions options) { + if (options.advanced.csvExport) { + try { + CsvComparisonOutput.writeCsvResults(result.getAllComparisons(), false, outputRoot, "results"); + CsvComparisonOutput.writeCsvResults(result.getAllComparisons(), true, outputRoot, "results-anonymous"); + } catch (IOException e) { + logger.warn("Could not write csv results", e); + } + } + } +} 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..3be42c8cd 100644 --- a/cli/src/main/java/de/jplag/cli/logger/CollectedLogger.java +++ b/cli/src/main/java/de/jplag/cli/logger/CollectedLogger.java @@ -73,14 +73,13 @@ 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(' '); // Append the name of the log instance - if (shortLogName == null) + if (shortLogName == null) { shortLogName = computeShortName(); + } builder.append(shortLogName).append(" - "); // Append the message builder.append(message); @@ -92,8 +91,9 @@ void printAllErrorsForLogger() { this.isFinalizing = true; // Copy errors to prevent infinite recursion var errors = new ArrayList<>(this.allErrors); - if (errors.isEmpty()) + if (errors.isEmpty()) { return; + } this.allErrors.removeAll(errors); @@ -140,6 +140,7 @@ private String renderLevel(int level) { }; } + @Override public boolean isTraceEnabled() { return isLevelEnabled(LOG_LEVEL_TRACE); } @@ -149,114 +150,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..e356763e3 100644 --- a/cli/src/main/java/de/jplag/cli/logger/CollectedLoggerFactory.java +++ b/cli/src/main/java/de/jplag/cli/logger/CollectedLoggerFactory.java @@ -23,15 +23,15 @@ public CollectedLoggerFactory() { /** * Return an appropriate {@link CollectedLogger} instance by name. */ + @Override public Logger getLogger(String name) { CollectedLogger simpleLogger = loggerMap.get(name); if (simpleLogger != null) { return simpleLogger; - } else { - CollectedLogger newInstance = new CollectedLogger(name); - Logger oldInstance = loggerMap.putIfAbsent(name, newInstance); - return oldInstance == null ? newInstance : oldInstance; } + CollectedLogger newInstance = new CollectedLogger(name); + Logger oldInstance = loggerMap.putIfAbsent(name, newInstance); + return oldInstance == null ? newInstance : oldInstance; } /** diff --git a/cli/src/main/java/de/jplag/cli/logger/TongfeiProgressBar.java b/cli/src/main/java/de/jplag/cli/logger/TongfeiProgressBar.java new file mode 100644 index 000000000..4305a497e --- /dev/null +++ b/cli/src/main/java/de/jplag/cli/logger/TongfeiProgressBar.java @@ -0,0 +1,24 @@ +package de.jplag.cli.logger; + +import de.jplag.logging.ProgressBar; + +/** + * A ProgressBar, that used the tongfei progress bar library underneath, to show progress bars on the cli. + */ +public class TongfeiProgressBar implements ProgressBar { + private final me.tongfei.progressbar.ProgressBar progressBar; + + public TongfeiProgressBar(me.tongfei.progressbar.ProgressBar progressBar) { + this.progressBar = progressBar; + } + + @Override + public void step(int number) { + this.progressBar.stepBy(number); + } + + @Override + public void dispose() { + this.progressBar.close(); + } +} diff --git a/cli/src/main/java/de/jplag/cli/logger/TongfeiProgressBarProvider.java b/cli/src/main/java/de/jplag/cli/logger/TongfeiProgressBarProvider.java new file mode 100644 index 000000000..da09fff33 --- /dev/null +++ b/cli/src/main/java/de/jplag/cli/logger/TongfeiProgressBarProvider.java @@ -0,0 +1,20 @@ +package de.jplag.cli.logger; + +import de.jplag.logging.ProgressBar; +import de.jplag.logging.ProgressBarProvider; +import de.jplag.logging.ProgressBarType; + +import me.tongfei.progressbar.ProgressBarBuilder; +import me.tongfei.progressbar.ProgressBarStyle; + +/** + * A ProgressBar provider, that used the tongfei progress bar library underneath, to show progress bars on the cli. + */ +public class TongfeiProgressBarProvider implements ProgressBarProvider { + @Override + public ProgressBar initProgressBar(ProgressBarType type, int totalSteps) { + me.tongfei.progressbar.ProgressBar progressBar = new ProgressBarBuilder().setTaskName(type.getDefaultText()).setInitialMax(totalSteps) + .setStyle(ProgressBarStyle.ASCII).build(); + return new TongfeiProgressBar(progressBar); + } +} diff --git a/cli/src/main/java/de/jplag/cli/server/ContentType.java b/cli/src/main/java/de/jplag/cli/server/ContentType.java new file mode 100644 index 000000000..cf90673b3 --- /dev/null +++ b/cli/src/main/java/de/jplag/cli/server/ContentType.java @@ -0,0 +1,41 @@ +package de.jplag.cli.server; + +/** + * Data types used by JPlag in the context of http. Contains the according mime type. + */ +public enum ContentType { + HTML("text/html; charset=utf-8", ".html"), + JS("application/javascript; charset=utf-8", ".js"), + CSS("text/css; charset=utf-8", ".css"), + PNG("image/png", ".png"), + PLAIN("text/plain; charset=utf-8", null), + ZIP("application/zip", ".zip"); + + private final String value; + + private final String nameSuffix; + + ContentType(String value, String nameSuffix) { + this.value = value; + this.nameSuffix = nameSuffix; + } + + public String getValue() { + return value; + } + + /** + * Guesses the type from the given path using the suffix after the last '.'. + * @param path The path to guess from + * @return The guessed type + */ + public static ContentType fromPath(String path) { + String suffix = path.substring(path.lastIndexOf('.')); + for (ContentType value : ContentType.values()) { + if (suffix.equals(value.nameSuffix)) { + return value; + } + } + return ContentType.PLAIN; + } +} diff --git a/cli/src/main/java/de/jplag/cli/server/HttpRequestMethod.java b/cli/src/main/java/de/jplag/cli/server/HttpRequestMethod.java new file mode 100644 index 000000000..acbf4a5b9 --- /dev/null +++ b/cli/src/main/java/de/jplag/cli/server/HttpRequestMethod.java @@ -0,0 +1,32 @@ +package de.jplag.cli.server; + +/** + * Wraps the http request methods used by JPlag. Request methods determine the capabilities of a http request. + */ +public enum HttpRequestMethod { + GET("GET"), + POST("POST"); + + private final String name; + + /** + * @param name The name of the request method + */ + HttpRequestMethod(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public static HttpRequestMethod fromName(String name) { + for (HttpRequestMethod value : HttpRequestMethod.values()) { + if (value.name.equals(name)) { + return value; + } + } + + return null; + } +} diff --git a/cli/src/main/java/de/jplag/cli/server/ReportViewer.java b/cli/src/main/java/de/jplag/cli/server/ReportViewer.java new file mode 100644 index 000000000..6e861c926 --- /dev/null +++ b/cli/src/main/java/de/jplag/cli/server/ReportViewer.java @@ -0,0 +1,133 @@ +package de.jplag.cli.server; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.BindException; +import java.net.InetAddress; +import java.net.InetSocketAddress; + +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.tuple.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; + +/** + * Manages the internal report viewer. Serves the static files for the report viewer and the results.zip. + */ +public class ReportViewer implements HttpHandler { + private static final String REPORT_VIEWER_RESOURCE_PREFIX = "report-viewer"; + private static final String INDEX_PATH = "index.html"; + private static final String RESULT_PATH = "results.zip"; + + private static final Logger logger = LoggerFactory.getLogger(ReportViewer.class); + private static final int SUCCESS_RESPONSE = 200; + private static final int NOT_FOUND_RESPONSE = 404; + private static final int MAX_PORT_LOOKUPS = 4; + + private final RoutingTree routingTree; + private final int port; + + private HttpServer server; + + /** + * @param zipFile The zip file to use for the report viewer + * @param port The port to use for the server. You can use 0 to use any free port. + * @throws IOException If the zip file cannot be read + */ + public ReportViewer(File zipFile, int port) throws IOException { + this.routingTree = new RoutingTree(); + + this.routingTree.insertRouting("", new RoutingResources(REPORT_VIEWER_RESOURCE_PREFIX).or(new RoutingAlias(INDEX_PATH))); + this.routingTree.insertRouting(RESULT_PATH, new RoutingStaticFile(zipFile, ContentType.ZIP)); + this.port = port; + } + + /** + * Starts the server and serves the internal report viewer. If available, the result.zip is also exposed. If the given + * port is already in use, the next free port will be used. + * @return The port the server runs at + * @throws IOException If the server cannot be started + */ + public int start() throws IOException { + if (server != null) { + throw new IllegalStateException("Server already started"); + } + + int currentPort = this.port; + int remainingLookups = MAX_PORT_LOOKUPS; + BindException lastException = new BindException("Could not create server. Probably due to no free port found."); + while (server == null && remainingLookups-- > 0) { + try { + server = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), currentPort), 0); + } catch (BindException e) { + logger.info("Port {} is not available. Trying to find a different one.", currentPort); + lastException = e; + currentPort++; + } + } + if (server == null) { + throw lastException; + } + server.createContext("/", this); + server.setExecutor(null); + server.start(); + + return server.getAddress().getPort(); + } + + /** + * Stops the server + */ + public void stop() { + server.stop(0); + } + + /** + * Do not call manually. Called by the running web server. + * @param exchange The http reqest + * @throws IOException If the IO handling goes wrong + */ + @Override + public void handle(HttpExchange exchange) throws IOException { + RoutingPath path = new RoutingPath(exchange.getRequestURI().getPath()); + Pair resolved = this.routingTree.resolveRouting(path); + HttpRequestMethod method = HttpRequestMethod.fromName(exchange.getRequestMethod()); + + if (resolved == null || !ArrayUtils.contains(resolved.getRight().allowedMethods(), method)) { + exchange.sendResponseHeaders(NOT_FOUND_RESPONSE, 0); + exchange.close(); + return; + } + + logger.debug("Serving {}", path); + + ResponseData responseData = resolved.getRight().fetchData(resolved.getLeft(), exchange, this); + if (responseData == null) { + logger.warn("No response data found for path: {}", path.asPath()); + exchange.sendResponseHeaders(NOT_FOUND_RESPONSE, 0); + exchange.close(); + return; + } + + InputStream inputStream = responseData.stream(); + + if (responseData.contentType() != null) { + exchange.getResponseHeaders().set("Content-Type", responseData.contentType().getValue()); + } + exchange.sendResponseHeaders(SUCCESS_RESPONSE, responseData.size()); + + inputStream.transferTo(exchange.getResponseBody()); + exchange.getResponseBody().flush(); + exchange.getResponseBody().close(); + inputStream.close(); + } + + RoutingTree getRoutingTree() { + return routingTree; + } +} diff --git a/cli/src/main/java/de/jplag/cli/server/ResponseData.java b/cli/src/main/java/de/jplag/cli/server/ResponseData.java new file mode 100644 index 000000000..26e9d037d --- /dev/null +++ b/cli/src/main/java/de/jplag/cli/server/ResponseData.java @@ -0,0 +1,46 @@ +package de.jplag.cli.server; + +import java.io.InputStream; + +/** + * Data for a http response + * @param stream The stream containing the binary data + * @param contentType The type of data + * @param size The total size of the data + */ +public record ResponseData(InputStream stream, ContentType contentType, int size) { + /** + * Constructor with unknown type and size. Type will be set to PLAIN. + * @param data The binary data to respond with + */ + public ResponseData(InputStream data) { + this(data, ContentType.PLAIN, 0); + } + + /** + * Constructor with unknown size + * @param data The binary data + * @param contentType The type of content + */ + public ResponseData(InputStream data, ContentType contentType) { + this(data, contentType, 0); + } + + /** + * Creates a new instance for a given resource url. + * @param url The resource url + * @return The new response data + */ + public static ResponseData fromResourceUrl(String url) { + if (url.endsWith("/")) { + return null; + } + + InputStream inputStream = ResponseData.class.getResourceAsStream(url); + + if (inputStream != null) { + return new ResponseData(inputStream, ContentType.fromPath(url)); + } + return null; + } +} diff --git a/cli/src/main/java/de/jplag/cli/server/Routing.java b/cli/src/main/java/de/jplag/cli/server/Routing.java new file mode 100644 index 000000000..a6152a031 --- /dev/null +++ b/cli/src/main/java/de/jplag/cli/server/Routing.java @@ -0,0 +1,33 @@ +package de.jplag.cli.server; + +import com.sun.net.httpserver.HttpExchange; + +/** + * Handles the data for a url prefix. + */ +public interface Routing { + /** + * @return The methods, that this routing can be used for. + */ + default HttpRequestMethod[] allowedMethods() { + return new HttpRequestMethod[] {HttpRequestMethod.GET}; + } + + /** + * Gets the data for the given url + * @param subPath The remaining suffix of the url, that is not jet interpreted + * @param request The original http request + * @param viewer The current report viewer + * @return The data to respond with + */ + ResponseData fetchData(RoutingPath subPath, HttpExchange request, ReportViewer viewer); + + /** + * Use the other routing if this routing does not find any data. + * @param other The other routing + * @return The combined routing + */ + default Routing or(Routing other) { + return new RoutingFallback(this, other); + } +} diff --git a/cli/src/main/java/de/jplag/cli/server/RoutingAlias.java b/cli/src/main/java/de/jplag/cli/server/RoutingAlias.java new file mode 100644 index 000000000..70c4aefe1 --- /dev/null +++ b/cli/src/main/java/de/jplag/cli/server/RoutingAlias.java @@ -0,0 +1,36 @@ +package de.jplag.cli.server; + +import org.apache.commons.lang3.tuple.Pair; + +import com.sun.net.httpserver.HttpExchange; + +/** + * An alias routing, that will respond with the response for a different path + */ +public class RoutingAlias implements Routing { + private final RoutingPath path; + + /** + * @param path The path to actually use + */ + public RoutingAlias(RoutingPath path) { + this.path = path; + } + + /** + * @param path The path to actually use + */ + public RoutingAlias(String path) { + this(new RoutingPath(path)); + } + + @Override + public ResponseData fetchData(RoutingPath subPath, HttpExchange request, ReportViewer viewer) { + Pair redirect = viewer.getRoutingTree().resolveRouting(path); + if (redirect == null) { + return null; + } + + return redirect.getValue().fetchData(redirect.getLeft(), request, viewer); + } +} diff --git a/cli/src/main/java/de/jplag/cli/server/RoutingFallback.java b/cli/src/main/java/de/jplag/cli/server/RoutingFallback.java new file mode 100644 index 000000000..13de6d6d2 --- /dev/null +++ b/cli/src/main/java/de/jplag/cli/server/RoutingFallback.java @@ -0,0 +1,30 @@ +package de.jplag.cli.server; + +import com.sun.net.httpserver.HttpExchange; + +/** + * Responds with the first given routing, unless that would respond with null, in that case the second one is used. + */ +public class RoutingFallback implements Routing { + private final Routing first; + private final Routing second; + + /** + * @param first The first routing + * @param second The second routing + */ + public RoutingFallback(Routing first, Routing second) { + this.first = first; + this.second = second; + } + + @Override + public ResponseData fetchData(RoutingPath subPath, HttpExchange request, ReportViewer viewer) { + ResponseData attempt = this.first.fetchData(subPath, request, viewer); + if (attempt != null) { + return attempt; + } + + return this.second.fetchData(subPath, request, viewer); + } +} diff --git a/cli/src/main/java/de/jplag/cli/server/RoutingPath.java b/cli/src/main/java/de/jplag/cli/server/RoutingPath.java new file mode 100644 index 000000000..e9263c8e8 --- /dev/null +++ b/cli/src/main/java/de/jplag/cli/server/RoutingPath.java @@ -0,0 +1,72 @@ +package de.jplag.cli.server; + +import java.util.Arrays; + +/** + * A path used for routing. Can be used like a linked list. + */ +public class RoutingPath { + private final String[] components; + private final int offset; + + /** + * @param path The full path + */ + public RoutingPath(String path) { + this.components = Arrays.stream(path.split("/", 0)).filter(it -> !it.isBlank()).toArray(String[]::new); + this.offset = 0; + } + + private RoutingPath(String[] components, int offset) { + this.components = components; + this.offset = offset; + } + + /** + * @return The first path segment + */ + public String head() { + return components[offset]; + } + + /** + * @return All path segments except the first + */ + public RoutingPath tail() { + if (!hasTail()) { + throw new IllegalStateException("Routing path is done."); + } + + return new RoutingPath(this.components, this.offset + 1); + } + + /** + * @return True, if the tail has at least 0 elements + */ + public boolean hasTail() { + return this.components.length > this.offset; + } + + /** + * @return True, if there are no segments in this path + */ + public boolean isEmpty() { + return this.offset == this.components.length; + } + + /** + * @return The remaining path as a string + */ + public String asPath() { + StringBuilder builder = new StringBuilder(); + + for (int i = this.offset; i < this.components.length; i++) { + if (i > this.offset) { + builder.append("/"); + } + builder.append(this.components[i]); + } + + return builder.toString(); + } +} diff --git a/cli/src/main/java/de/jplag/cli/server/RoutingResources.java b/cli/src/main/java/de/jplag/cli/server/RoutingResources.java new file mode 100644 index 000000000..d46a8fe43 --- /dev/null +++ b/cli/src/main/java/de/jplag/cli/server/RoutingResources.java @@ -0,0 +1,31 @@ +package de.jplag.cli.server; + +import com.sun.net.httpserver.HttpExchange; + +/** + * Responds with data from the resources + */ +public class RoutingResources implements Routing { + private String prefix; + + /** + * @param prefix The prefix to use within the resources + */ + public RoutingResources(String prefix) { + this.prefix = prefix; + + if (!this.prefix.startsWith("/")) { + this.prefix = "/" + this.prefix; + } + + if (!this.prefix.endsWith("/")) { + this.prefix = this.prefix + "/"; + } + } + + @Override + public ResponseData fetchData(RoutingPath subPath, HttpExchange request, ReportViewer viewer) { + String fullPath = this.prefix + subPath.asPath(); + return ResponseData.fromResourceUrl(fullPath); + } +} diff --git a/cli/src/main/java/de/jplag/cli/server/RoutingStaticFile.java b/cli/src/main/java/de/jplag/cli/server/RoutingStaticFile.java new file mode 100644 index 000000000..3ce5bed1a --- /dev/null +++ b/cli/src/main/java/de/jplag/cli/server/RoutingStaticFile.java @@ -0,0 +1,42 @@ +package de.jplag.cli.server; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +import com.sun.net.httpserver.HttpExchange; + +/** + * Responds with a given file + */ +public class RoutingStaticFile implements Routing { + private final byte[] data; + private final ContentType contentType; + + /** + * @param file The file to use + * @param contentType The type of content in the file + * @throws IOException If the file cannot be read + */ + public RoutingStaticFile(File file, ContentType contentType) throws IOException { + if (file != null) { + try (FileInputStream inputStream = new FileInputStream(file)) { + this.data = inputStream.readAllBytes(); + + this.contentType = contentType; + } + } else { + this.data = null; + this.contentType = contentType; + } + } + + @Override + public ResponseData fetchData(RoutingPath subPath, HttpExchange request, ReportViewer viewer) { + if (this.data != null) { + return new ResponseData(new ByteArrayInputStream(this.data), contentType, this.data.length); + } + return null; + } +} diff --git a/cli/src/main/java/de/jplag/cli/server/RoutingTree.java b/cli/src/main/java/de/jplag/cli/server/RoutingTree.java new file mode 100644 index 000000000..83bc4dff3 --- /dev/null +++ b/cli/src/main/java/de/jplag/cli/server/RoutingTree.java @@ -0,0 +1,87 @@ +package de.jplag.cli.server; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang3.tuple.Pair; + +/** + * Manages the tree of paths handled by the web server + */ +public class RoutingTree { + private final RoutingTreeNode root; + + /** + * Creates an empty tree + */ + public RoutingTree() { + this.root = new RoutingTreeNode(); + } + + /** + * Adds a new routing to the tree + * @param path The path to use the routing for + * @param routing The routing + */ + public void insertRouting(RoutingPath path, Routing routing) { + this.root.buildRouting(path, routing); + } + + /** + * Adds a new routing to the tree + * @param path The path to use the routing for + * @param routing The routing + */ + public void insertRouting(String path, Routing routing) { + this.insertRouting(new RoutingPath(path), routing); + } + + /** + * Gets the routing for a given path + * @param path The path to look up + * @return The remaining path to be handled by the routing and the found routing + */ + public Pair resolveRouting(RoutingPath path) { + return this.root.resolve(path); + } + + private static class RoutingTreeNode { + private final Map children; + private Routing routing; + + public RoutingTreeNode(RoutingPath building, Routing routing) { + this(); + this.buildRouting(building, routing); + } + + public RoutingTreeNode() { + this.children = new HashMap<>(); + } + + public void buildRouting(RoutingPath building, Routing routing) { + if (building.isEmpty()) { + this.routing = routing; + } else if (this.children.containsKey(building.head())) { + this.children.get(building.head()).buildRouting(building.tail(), routing); + } else { + this.children.put(building.head(), new RoutingTreeNode(building.tail(), routing)); + } + } + + public Pair resolve(RoutingPath path) { + if ((path.isEmpty() || !this.children.containsKey(path.head())) && this.routing != null) { + return Pair.of(path, this.routing); + } + + if (this.children.containsKey(path.head()) && !path.isEmpty()) { + Pair childResolved = this.children.get(path.head()).resolve(path.tail()); + if (childResolved == null && this.routing != null) { + return Pair.of(path, this.routing); + } + return childResolved; + } + + return null; + } + } +} diff --git a/cli/src/main/resources/README.md b/cli/src/main/resources/README.md new file mode 100644 index 000000000..5355d847c --- /dev/null +++ b/cli/src/main/resources/README.md @@ -0,0 +1 @@ +Copy ReportViewer to a directory called `JPlag` \ No newline at end of file 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..75ee12124 100644 --- a/cli/src/test/java/de/jplag/cli/ClusteringTest.java +++ b/cli/src/test/java/de/jplag/cli/ClusteringTest.java @@ -1,6 +1,8 @@ package de.jplag.cli; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; @@ -8,40 +10,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..6561c8034 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(19, 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/MergingOptionsTest.java b/cli/src/test/java/de/jplag/cli/MergingOptionsTest.java new file mode 100644 index 000000000..bf2b642c7 --- /dev/null +++ b/cli/src/test/java/de/jplag/cli/MergingOptionsTest.java @@ -0,0 +1,25 @@ +package de.jplag.cli; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import de.jplag.merging.MergingOptions; + +/** + * Test cases for the options of the match merging mechanism. + */ +class MergingOptionsTest extends CommandLineInterfaceTest { + + @Test + @DisplayName("Test if default values are used when creating merging options from CLI") + void testMergingDefault() throws CliException { + buildOptionsFromCLI(defaultArguments()); + assertNotNull(options.mergingOptions()); + assertEquals(MergingOptions.DEFAULT_ENABLED, options.mergingOptions().enabled()); + assertEquals(MergingOptions.DEFAULT_NEIGHBOR_LENGTH, options.mergingOptions().minimumNeighborLength()); + assertEquals(MergingOptions.DEFAULT_GAP_SIZE, options.mergingOptions().maximumGapSize()); + } +} 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/ReportViewerTest.java b/cli/src/test/java/de/jplag/cli/ReportViewerTest.java new file mode 100644 index 000000000..cc5f592ce --- /dev/null +++ b/cli/src/test/java/de/jplag/cli/ReportViewerTest.java @@ -0,0 +1,33 @@ +package de.jplag.cli; + +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +import java.awt.Desktop; +import java.net.URI; +import java.util.concurrent.TimeUnit; + +import javax.swing.JOptionPane; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; + +import de.jplag.cli.server.ReportViewer; + +@Timeout(value = 5, unit = TimeUnit.MINUTES) +class ReportViewerTest { + @Test + @Disabled("Starts the internal server for manual testing. Does not terminal automatically.") + void testStartViewer() throws Exception { + assumeTrue(Desktop.isDesktopSupported()); + ReportViewer viewer = new ReportViewer(null, 0); + + int port = viewer.start(); + Desktop.getDesktop().browse(URI.create("http://localhost:" + port)); + + // Open Dialog to keep the test running + JOptionPane.showMessageDialog(null, "Press OK to stop the server"); + viewer.stop(); + } + +} \ No newline at end of file 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/cli/src/test/java/de/jplag/cli/server/RoutingFallbackTest.java b/cli/src/test/java/de/jplag/cli/server/RoutingFallbackTest.java new file mode 100644 index 000000000..6dc08d057 --- /dev/null +++ b/cli/src/test/java/de/jplag/cli/server/RoutingFallbackTest.java @@ -0,0 +1,44 @@ +package de.jplag.cli.server; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +import java.io.File; +import java.io.IOException; + +import org.junit.jupiter.api.Test; + +class RoutingFallbackTest { + private final Routing nullRouting; + private final Routing contentRouting; + + RoutingFallbackTest() throws IOException { + File testFile = File.createTempFile("content", ".any"); + this.nullRouting = new RoutingStaticFile(null, ContentType.PLAIN); + this.contentRouting = new RoutingStaticFile(testFile, ContentType.PLAIN); + } + + @Test + void testSecondNull() { + Routing routing = this.nullRouting.or(this.contentRouting); + assertNotNull(routing.fetchData(null, null, null)); + } + + @Test + void testFirstNull() { + Routing routing = this.contentRouting.or(this.nullRouting); + assertNotNull(routing.fetchData(null, null, null)); + } + + @Test + void testNeitherNull() { + Routing routing = this.contentRouting.or(this.contentRouting); + assertNotNull(routing.fetchData(null, null, null)); + } + + @Test + void testBothNull() { + Routing routing = this.nullRouting.or(this.nullRouting); + assertNull(routing.fetchData(null, null, null)); + } +} \ No newline at end of file diff --git a/cli/src/test/java/de/jplag/cli/server/RoutingPathTest.java b/cli/src/test/java/de/jplag/cli/server/RoutingPathTest.java new file mode 100644 index 000000000..e4c2ebff0 --- /dev/null +++ b/cli/src/test/java/de/jplag/cli/server/RoutingPathTest.java @@ -0,0 +1,46 @@ +package de.jplag.cli.server; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +class RoutingPathTest { + private static final String TEST_PATH = "some/path/to/index.html"; + private static final String TEST_PATH_WITH_BEGINNING_SLASH = "/some/path/to/index.html"; + private static final String TEST_PATH_WITH_ADDITIONAL_SLASHES = "///some/path////to/index.html"; + + private static final String[] TEST_PATH_PARTS = new String[] {"some", "path", "to", "index.html"}; + + @ParameterizedTest + @ValueSource(strings = {TEST_PATH_WITH_BEGINNING_SLASH, TEST_PATH, TEST_PATH_WITH_ADDITIONAL_SLASHES}) + void testAsPath(String path) { + RoutingPath routingPath = new RoutingPath(path); + assertEquals(TEST_PATH, routingPath.asPath()); + } + + @Test + void testIterating() { + RoutingPath routingPath = new RoutingPath(TEST_PATH); + for (String expectedPart : TEST_PATH_PARTS) { + String currentPart = routingPath.head(); + routingPath = routingPath.tail(); + assertEquals(expectedPart, currentPart); + } + + assertFalse(routingPath.hasTail()); + assertTrue(routingPath.isEmpty()); + } + + @Test + void testErrorWithEmptyTail() { + assertThrowsExactly(IllegalStateException.class, () -> { + RoutingPath routingPath = new RoutingPath(""); + routingPath.tail(); + }); + } +} \ No newline at end of file diff --git a/cli/src/test/java/de/jplag/cli/server/RoutingResourcesTest.java b/cli/src/test/java/de/jplag/cli/server/RoutingResourcesTest.java new file mode 100644 index 000000000..56df92140 --- /dev/null +++ b/cli/src/test/java/de/jplag/cli/server/RoutingResourcesTest.java @@ -0,0 +1,20 @@ +package de.jplag.cli.server; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +import org.junit.jupiter.api.Test; + +class RoutingResourcesTest { + private static final RoutingResources routing = new RoutingResources("/"); + + @Test + void testExistingFile() { + assertNotNull(routing.fetchData(new RoutingPath("testResource.txt"), null, null)); + } + + @Test + void testNotExistingFile() { + assertNull(routing.fetchData(new RoutingPath("otherFile.txt"), null, null)); + } +} \ No newline at end of file diff --git a/cli/src/test/java/de/jplag/cli/server/RoutingStaticFileTest.java b/cli/src/test/java/de/jplag/cli/server/RoutingStaticFileTest.java new file mode 100644 index 000000000..8e9549d00 --- /dev/null +++ b/cli/src/test/java/de/jplag/cli/server/RoutingStaticFileTest.java @@ -0,0 +1,43 @@ +package de.jplag.cli.server; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStreamReader; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +class RoutingStaticFileTest { + private static final String TEST_FILE_CONTENT = "some test content."; + private static final ContentType TEST_CONTENT_TYPE = ContentType.PLAIN; + private static RoutingStaticFile routing; + + @BeforeAll + static void setUp() throws IOException { + File testFile = File.createTempFile("testFile", ".txt"); + try (FileWriter writer = new FileWriter(testFile)) { + writer.write(TEST_FILE_CONTENT); + } + routing = new RoutingStaticFile(testFile, TEST_CONTENT_TYPE); + } + + @Test + void testRespondsWithFileContent() throws IOException { + ResponseData responseData = routing.fetchData(null, null, null); + assertEquals(TEST_CONTENT_TYPE, responseData.contentType()); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(responseData.stream()))) { + assertEquals(TEST_FILE_CONTENT, reader.readLine()); + } + } + + @Test + void testWithNullFile() throws IOException { + RoutingStaticFile nullRouting = new RoutingStaticFile(null, TEST_CONTENT_TYPE); + assertNull(nullRouting.fetchData(null, null, null)); + } +} \ No newline at end of file diff --git a/cli/src/test/java/de/jplag/cli/server/RoutingTreeTest.java b/cli/src/test/java/de/jplag/cli/server/RoutingTreeTest.java new file mode 100644 index 000000000..318c00db2 --- /dev/null +++ b/cli/src/test/java/de/jplag/cli/server/RoutingTreeTest.java @@ -0,0 +1,80 @@ +package de.jplag.cli.server; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.apache.commons.lang3.tuple.Pair; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import com.sun.net.httpserver.HttpExchange; + +class RoutingTreeTest { + private static final String firstRoutingPath = "/content/image.png"; + private static final String secondRoutingPath = "/index.html"; + private RoutingTree routingTree; + + @BeforeEach + void setUp() { + this.routingTree = new RoutingTree(); + this.routingTree.insertRouting(firstRoutingPath, new TestRouting(firstRoutingPath)); + this.routingTree.insertRouting(secondRoutingPath, new TestRouting(secondRoutingPath)); + } + + @Test + void testAccessRoutingTree() { + Pair firstRouting = this.routingTree.resolveRouting(new RoutingPath(firstRoutingPath)); + Pair secondRouting = this.routingTree.resolveRouting(new RoutingPath(secondRoutingPath + "/suffix")); + + assertTrue(firstRouting.getLeft().isEmpty()); + assertFalse(secondRouting.getLeft().isEmpty()); + assertEquals("suffix", secondRouting.getLeft().asPath()); + + assertInstanceOf(TestRouting.class, firstRouting.getRight()); + assertInstanceOf(TestRouting.class, secondRouting.getRight()); + + assertEquals(firstRoutingPath, ((TestRouting) firstRouting.getRight()).path); + assertEquals(secondRoutingPath, ((TestRouting) secondRouting.getRight()).path); + } + + @Test + void testUnknownPath() { + assertNull(this.routingTree.resolveRouting(new RoutingPath("/unknown.html"))); + } + + @Test + void testPartialPathRoute() { + RoutingTree routingTree = new RoutingTree(); + routingTree.insertRouting("/path/", new TestRouting("")); + assertNotNull(routingTree.resolveRouting(new RoutingPath("/path/index.html"))); + } + + @Test + void testPartialPathRouteWithSubpath() { + RoutingTree routingTree = new RoutingTree(); + routingTree.insertRouting("/path/", new TestRouting("/path/")); + routingTree.insertRouting("/path/subPath/a.html", new TestRouting("")); + + Pair result = routingTree.resolveRouting(new RoutingPath("/path/subPath/b.html")); + assertNotNull(result); + assertInstanceOf(TestRouting.class, result.getRight()); + assertEquals("/path/", ((TestRouting) result.getRight()).path); + } + + private static class TestRouting implements Routing { + private final String path; + + public TestRouting(String path) { + this.path = path; + } + + @Override + public ResponseData fetchData(RoutingPath subPath, HttpExchange request, ReportViewer viewer) { + return null; + } + } +} \ No newline at end of file diff --git a/cli/src/test/resources/testResource.txt b/cli/src/test/resources/testResource.txt new file mode 100644 index 000000000..c29d01b9b --- /dev/null +++ b/cli/src/test/resources/testResource.txt @@ -0,0 +1 @@ +Test resource file for RoutingResourcesTest \ No newline at end of file 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..3cef93354 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,15 @@ 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 submissionComparator = Comparator.comparing((Submission it) -> it.getTokenList().size()) + .thenComparing(Submission::getName); + + if (submissionComparator.compare(firstSubmission, secondSubmission) <= 0) { smallerSubmission = firstSubmission; largerSubmission = secondSubmission; + } else { + smallerSubmission = secondSubmission; + largerSubmission = firstSubmission; } return compareInternal(smallerSubmission, largerSubmission); } @@ -92,43 +98,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 +139,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 +161,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 +195,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..41f1c08c8 100644 --- a/core/src/main/java/de/jplag/JPlag.java +++ b/core/src/main/java/de/jplag/JPlag.java @@ -1,13 +1,20 @@ package de.jplag; +import java.io.File; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; import java.util.ResourceBundle; +import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import de.jplag.clustering.ClusteringFactory; import de.jplag.exceptions.ExitException; +import de.jplag.exceptions.RootDirectoryException; 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,30 +37,43 @@ 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 { + checkForConfigurationConsistency(options); + 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(); - + if (options.normalize() && options.language().supportsNormalization() && options.language().requiresCoreNormalization()) { + submissionSet.normalizeSubmissions(); + } int submissionCount = submissionSet.numberOfSubmissions(); if (submissionCount < 2) { throw new SubmissionException("Not enough valid submissions! (found " + submissionCount + " valid submissions)"); @@ -61,11 +81,56 @@ public JPlagResult run() throws ExitException { // Compare valid submissions. JPlagResult result = comparisonStrategy.compareSubmissions(submissionSet); - if (logger.isInfoEnabled()) - logger.info("Total time for comparing submissions: {}", TimeUtil.formatDuration(result.getDuration())); + // 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()); + } + } + } + + private static void checkForConfigurationConsistency(JPlagOptions options) throws RootDirectoryException { + if (options.normalize() && !options.language().supportsNormalization()) { + logger.error(String.format("The language %s cannot be used with normalization.", options.language().getName())); + } + + List duplicateNames = getDuplicateSubmissionFolderNames(options); + if (duplicateNames.size() > 0) { + throw new RootDirectoryException(String.format("Duplicate root directory names found: %s", String.join(", ", duplicateNames))); + } + } + + private static List getDuplicateSubmissionFolderNames(JPlagOptions options) { + List duplicateNames = new ArrayList<>(); + Set alreadyFoundNames = new HashSet<>(); + for (File file : options.submissionDirectories()) { + if (!alreadyFoundNames.add(file.getName())) { + duplicateNames.add(file.getName()); + } + } + for (File file : options.oldSubmissionDirectories()) { + if (!alreadyFoundNames.add(file.getName())) { + duplicateNames.add(file.getName()); + } + } + return duplicateNames; + } } 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..581079b87 100644 --- a/core/src/main/java/de/jplag/JPlagResult.java +++ b/core/src/main/java/de/jplag/JPlagResult.java @@ -1,5 +1,6 @@ package de.jplag; +import java.util.Comparator; import java.util.List; import java.util.function.ToDoubleFunction; @@ -23,11 +24,11 @@ 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) - this.comparisons = comparisons.stream().sorted((first, second) -> Double.compare(second.similarity(), first.similarity())).toList(); + this.comparisons = comparisons.stream().sorted(Comparator.comparing(JPlagComparison::similarity).reversed()).toList(); this.submissions = submissions; this.durationInMillis = durationInMillis; this.options = options; diff --git a/core/src/main/java/de/jplag/Match.java b/core/src/main/java/de/jplag/Match.java index deaad733d..1e94315a7 100644 --- a/core/src/main/java/de/jplag/Match.java +++ b/core/src/main/java/de/jplag/Match.java @@ -16,17 +16,14 @@ public boolean overlaps(Match other) { if ((other.startOfFirst - startOfFirst) < length) { return true; } - } else { - if ((startOfFirst - other.startOfFirst) < other.length) { - return true; - } + } else if ((startOfFirst - other.startOfFirst) < other.length) { + return true; } if (startOfSecond < other.startOfSecond) { return (other.startOfSecond - startOfSecond) < length; - } else { - return (startOfSecond - other.startOfSecond) < other.length; } + return (startOfSecond - other.startOfSecond) < other.length; } /** diff --git a/core/src/main/java/de/jplag/Messages.java b/core/src/main/java/de/jplag/Messages.java deleted file mode 100644 index b39549612..000000000 --- a/core/src/main/java/de/jplag/Messages.java +++ /dev/null @@ -1,21 +0,0 @@ -package de.jplag; - -import java.util.MissingResourceException; -import java.util.ResourceBundle; - -public class Messages { - private static final String BUNDLE_NAME = "de.jplag.messages"; //$NON-NLS-1$ - - private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME); - - private Messages() { - } - - public static String getString(String key) { - try { - return RESOURCE_BUNDLE.getString(key); - } catch (MissingResourceException e) { - return '!' + key + '!'; - } - } -} diff --git a/core/src/main/java/de/jplag/NumberOfArgumentValues.java b/core/src/main/java/de/jplag/NumberOfArgumentValues.java deleted file mode 100644 index 8a4987c2a..000000000 --- a/core/src/main/java/de/jplag/NumberOfArgumentValues.java +++ /dev/null @@ -1,21 +0,0 @@ -package de.jplag; - -/** - * Allowed number of values of a command-line argument in the CLI. - */ -public enum NumberOfArgumentValues { - SINGLE_VALUE(""), - ONE_OR_MORE_VALUES("+"), - ZERO_OR_MORE_VALUES("*"); - - private final String representation; - - NumberOfArgumentValues(String representation) { - this.representation = representation; - } - - @Override - public String toString() { - return representation; - } -} \ No newline at end of file diff --git a/core/src/main/java/de/jplag/Submission.java b/core/src/main/java/de/jplag/Submission.java index 576af0fbd..0fe8db33f 100644 --- a/core/src/main/java/de/jplag/Submission.java +++ b/core/src/main/java/de/jplag/Submission.java @@ -4,26 +4,28 @@ 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.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; 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). */ @@ -61,6 +63,8 @@ public class Submission implements Comparable { private final Language language; + private Map fileTokenCount; + /** * Creates a submission. * @param name Identification of the submission (directory or filename). @@ -222,7 +226,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(); } @@ -235,9 +239,11 @@ private static File createErrorDirectory(String... subdirectoryNames) { /** * Parse files of the submission. + * @param debugParser specifies if the submission should be copied upon parsing errors. + * @param normalize specifies if the tokens sequences should be normalized. * @return Whether parsing was successful. */ - /* package-private */ boolean parse(boolean debugParser) { + /* package-private */ boolean parse(boolean debugParser, boolean normalize) { if (files == null || files.isEmpty()) { logger.error("ERROR: nothing to parse for submission \"{}\"", name); tokenList = null; @@ -246,9 +252,15 @@ private static File createErrorDirectory(String... subdirectoryNames) { } try { - tokenList = language.parse(new HashSet<>(files)); + tokenList = language.parse(new HashSet<>(files), normalize); + if (logger.isDebugEnabled()) { + for (Token token : tokenList) { + logger.debug(String.join(" | ", token.getType().toString(), Integer.toString(token.getLine()), token.getSemantics().toString())); + } + } } catch (ParsingException e) { - logger.warn("Failed to parse submission {} with error {}", this, e); + String shortenedMessage = e.getMessage().replace(submissionRootFile.toString(), name); + logger.warn("Failed to parse submission {}:{}{}", name, System.lineSeparator(), shortenedMessage); tokenList = null; hasErrors = true; if (debugParser) { @@ -265,4 +277,63 @@ private static File createErrorDirectory(String... subdirectoryNames) { } return true; } + + /** + * Perform token sequence normalization, which makes the token sequence invariant to dead code insertion and independent + * statement reordering. + */ + void normalize() { + List originalOrder = getOrder(tokenList); + 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; + } + + /** + * @return A mapping of each file in the submission to the number of tokens in the file + */ + public Map getTokenCountPerFile() { + if (this.tokenList == null) { + return Collections.emptyMap(); + } + + if (fileTokenCount == null) { + fileTokenCount = new HashMap<>(); + for (File file : this.files) { + fileTokenCount.put(file, 0); + } + for (Token token : this.tokenList) { + fileTokenCount.put(token.getFile(), fileTokenCount.get(token.getFile()) + 1); + } + } + return fileTokenCount; + } } diff --git a/core/src/main/java/de/jplag/SubmissionFileData.java b/core/src/main/java/de/jplag/SubmissionFileData.java new file mode 100644 index 000000000..91eb3edda --- /dev/null +++ b/core/src/main/java/de/jplag/SubmissionFileData.java @@ -0,0 +1,13 @@ +package de.jplag; + +import java.io.File; + +/** + * Contains the information about a single file in a submission. For single file submissions the submission file is the + * same as the root. + * @param submissionFile The file, that is part of a submission + * @param root The root of the submission + * @param isNew Indicates weather this follows the new or the old syntax + */ +public record SubmissionFileData(File submissionFile, File root, boolean isNew) { +} diff --git a/core/src/main/java/de/jplag/SubmissionSet.java b/core/src/main/java/de/jplag/SubmissionSet.java index 5fd637324..907687974 100644 --- a/core/src/main/java/de/jplag/SubmissionSet.java +++ b/core/src/main/java/de/jplag/SubmissionSet.java @@ -10,6 +10,9 @@ import de.jplag.exceptions.BasecodeException; import de.jplag.exceptions.ExitException; import de.jplag.exceptions.SubmissionException; +import de.jplag.logging.ProgressBar; +import de.jplag.logging.ProgressBarLogger; +import de.jplag.logging.ProgressBarType; import de.jplag.options.JPlagOptions; /** @@ -37,6 +40,7 @@ public class SubmissionSet { /** * @param submissions Submissions to check for plagiarism. * @param baseCode Base code submission if it exists or {@code null}. + * @param options The JPlag options */ public SubmissionSet(List submissions, Submission baseCode, JPlagOptions options) throws ExitException { this.allSubmissions = submissions; @@ -90,6 +94,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)); } @@ -115,10 +123,12 @@ private void parseAllSubmissions() throws ExitException { private void parseBaseCodeSubmission(Submission baseCode) throws BasecodeException { long startTime = System.currentTimeMillis(); logger.trace("----- Parsing basecode submission: " + baseCode.getName()); - if (!baseCode.parse(options.debugParser())) { + if (!baseCode.parse(options.debugParser(), options.normalize())) { 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!"); + } + if (baseCode.getNumberOfTokens() < options.minimumTokenMatch()) { + 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; @@ -128,6 +138,7 @@ private void parseBaseCodeSubmission(Submission baseCode) throws BasecodeExcepti /** * Parse all given submissions. + * @param submissions The list of submissions */ private void parseSubmissions(List submissions) { if (submissions.isEmpty()) { @@ -138,18 +149,20 @@ private void parseSubmissions(List submissions) { long startTime = System.currentTimeMillis(); int tooShort = 0; + ProgressBar progressBar = ProgressBarLogger.createProgressBar(ProgressBarType.PARSING, submissions.size()); for (Submission submission : submissions) { boolean ok; logger.trace("------ Parsing submission: " + submission.getName()); currentSubmissionName = submission.getName(); - if (!(ok = submission.parse(options.debugParser()))) { + if (!(ok = submission.parse(options.debugParser(), options.normalize()))) { errors++; } 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; @@ -161,7 +174,9 @@ private void parseSubmissions(List submissions) { } else { logger.error("ERROR -> Submission {} removed", currentSubmissionName); } + progressBar.step(); } + progressBar.dispose(); int validSubmissions = submissions.size() - errors - tooShort; logger.trace(validSubmissions + " submissions parsed successfully!"); diff --git a/core/src/main/java/de/jplag/SubmissionSetBuilder.java b/core/src/main/java/de/jplag/SubmissionSetBuilder.java index ff567e847..e0cf584e4 100644 --- a/core/src/main/java/de/jplag/SubmissionSetBuilder.java +++ b/core/src/main/java/de/jplag/SubmissionSetBuilder.java @@ -6,6 +6,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -21,6 +22,9 @@ import de.jplag.exceptions.ExitException; import de.jplag.exceptions.RootDirectoryException; import de.jplag.exceptions.SubmissionException; +import de.jplag.logging.ProgressBar; +import de.jplag.logging.ProgressBarLogger; +import de.jplag.logging.ProgressBarType; import de.jplag.options.JPlagOptions; /** @@ -31,19 +35,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. * @param language is the language of the submissions. * @param options are the configured options. + * @deprecated in favor of {@link #SubmissionSetBuilder(JPlagOptions)}. */ + @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(); } /** @@ -61,20 +71,34 @@ public SubmissionSet buildSubmissionSet() throws ExitException { int numberOfRootDirectories = submissionDirectories.size() + oldSubmissionDirectories.size(); boolean multipleRoots = (numberOfRootDirectories > 1); - // Collect valid looking entries from the root directories. - Map foundSubmissions = new HashMap<>(); - for (File directory : submissionDirectories) { - processRootDirectoryEntries(directory, multipleRoots, foundSubmissions, true); + List submissionFiles = new ArrayList<>(); + for (File submissionDirectory : submissionDirectories) { + submissionFiles.addAll(listSubmissionFiles(submissionDirectory, true)); } - for (File oldDirectory : oldSubmissionDirectories) { - processRootDirectoryEntries(oldDirectory, multipleRoots, foundSubmissions, false); + for (File submissionDirectory : oldSubmissionDirectories) { + submissionFiles.addAll(listSubmissionFiles(submissionDirectory, false)); } + ProgressBar progressBar = ProgressBarLogger.createProgressBar(ProgressBarType.LOADING, submissionFiles.size()); + Map foundSubmissions = new HashMap<>(); + for (SubmissionFileData submissionFile : submissionFiles) { + processSubmissionFile(submissionFile, multipleRoots, foundSubmissions); + progressBar.step(); + } + progressBar.dispose(); + Optional baseCodeSubmission = loadBaseCode(); baseCodeSubmission.ifPresent(baseSubmission -> foundSubmissions.remove(baseSubmission.getRoot())); // 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(Submission::getRoot).toList(); + rootFiles = options.language().customizeSubmissionOrder(rootFiles); + submissions = new ArrayList<>(rootFiles.stream().map(foundSubmissions::get).toList()); + } return new SubmissionSet(submissions, baseCodeSubmission.orElse(null), options); } @@ -142,31 +166,25 @@ private Optional loadBaseCode() throws ExitException { Submission baseCodeSubmission = processSubmission(baseCodeSubmissionDirectory.getName(), baseCodeSubmissionDirectory, false); logger.info("Basecode directory \"{}\" will be used.", baseCodeSubmission.getName()); - return Optional.ofNullable(baseCodeSubmission); + return Optional.of(baseCodeSubmission); } - /** - * Read entries in the given root directory. - */ - private String[] listSubmissionFiles(File rootDirectory) throws ExitException { + private List listSubmissionFiles(File rootDirectory, boolean isNew) throws RootDirectoryException { if (!rootDirectory.isDirectory()) { throw new AssertionError("Given root is not a directory."); } - String[] fileNames; - try { - fileNames = rootDirectory.list(); + File[] files = rootDirectory.listFiles(); + if (files == null) { + throw new RootDirectoryException("Cannot list files of the root directory!"); + } + + return Arrays.stream(files).sorted(Comparator.comparing(File::getName)).map(it -> new SubmissionFileData(it, rootDirectory, isNew)) + .toList(); } catch (SecurityException exception) { throw new RootDirectoryException("Cannot list files of the root directory! " + exception.getMessage(), exception); } - - if (fileNames == null) { - throw new RootDirectoryException("Cannot list files of the root directory!"); - } - - Arrays.sort(fileNames); - return fileNames; } /** @@ -187,6 +205,7 @@ private String isExcludedEntry(File submissionEntry) { /** * Process the given directory entry as a submission, the path MUST not be excluded. + * @param submissionName The name of the submission * @param submissionFile the file for the submission. * @param isNew states whether submissions found in the root directory must be checked for plagiarism. * @return The entry converted to a submission. @@ -209,30 +228,19 @@ 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()); } - /** - * Process entries in the root directory to check whether they qualify as submissions. - * @param rootDirectory is the root directory being examined. - * @param foundSubmissions Submissions found so far, is updated in-place. - * @param isNew states whether submissions found in the root directory must be checked for plagiarism. - */ - private void processRootDirectoryEntries(File rootDirectory, boolean multipleRoots, Map foundSubmissions, boolean isNew) - throws ExitException { - for (String fileName : listSubmissionFiles(rootDirectory)) { - File submissionFile = new File(rootDirectory, fileName); - - String errorMessage = isExcludedEntry(submissionFile); - if (errorMessage == null) { - String rootDirectoryPrefix = multipleRoots ? (rootDirectory.getName() + File.separator) : ""; - String submissionName = rootDirectoryPrefix + fileName; - Submission submission = processSubmission(submissionName, submissionFile, isNew); - foundSubmissions.put(submission.getRoot(), submission); - } else { - logger.error(errorMessage); - } + private void processSubmissionFile(SubmissionFileData file, boolean multipleRoots, Map foundSubmissions) throws ExitException { + String errorMessage = isExcludedEntry(file.submissionFile()); + if (errorMessage != null) { + logger.error(errorMessage); } + + String rootDirectoryPrefix = multipleRoots ? (file.root().getName() + File.separator) : ""; + String submissionName = rootDirectoryPrefix + file.submissionFile().getName(); + Submission submission = processSubmission(submissionName, file.submissionFile(), file.isNew()); + foundSubmissions.put(submission.getRoot(), submission); } /** @@ -254,7 +262,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)); } /** @@ -298,4 +306,5 @@ private File makeCanonical(File file, Function excepti throw exceptionWrapper.apply(exception); } } + } diff --git a/core/src/main/java/de/jplag/SubsequenceHashLookupTable.java b/core/src/main/java/de/jplag/SubsequenceHashLookupTable.java index 7260b7c02..e19a41643 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,17 +43,7 @@ class SubsequenceHashLookupTable { subsequenceHashes = new int[values.length - windowSize]; startIndexToSubsequenceHashesMap = new HashMap<>(subsequenceHashes.length); - computeSubsequenceHashes(markedIndexes); - } - - /** Returns the size of the subsequences used for hashing */ - int getWindowSize() { - return windowSize; - } - - /** Returns the list of values for which the hashes were computed */ - int[] getValues() { - return values; + computeSubsequenceHashes(marked); } /** @@ -82,10 +70,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 +90,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/clustering/ClusteringOptions.java b/core/src/main/java/de/jplag/clustering/ClusteringOptions.java index 808311df3..313623869 100644 --- a/core/src/main/java/de/jplag/clustering/ClusteringOptions.java +++ b/core/src/main/java/de/jplag/clustering/ClusteringOptions.java @@ -6,6 +6,8 @@ import de.jplag.clustering.algorithm.InterClusterSimilarity; import de.jplag.options.SimilarityMetric; +import com.fasterxml.jackson.annotation.JsonProperty; + /** * Collection of all possible parameters that describe how a clustering should be performed. * @param similarityMetric The similarity metric is used for clustering @@ -34,10 +36,15 @@ * @param preprocessorPercentile up to which percentile of similarities the percentile-preprocessor zeroes out the * similarities */ -public record ClusteringOptions(SimilarityMetric similarityMetric, double spectralKernelBandwidth, double spectralGaussianProcessVariance, - int spectralMinRuns, int spectralMaxRuns, int spectralMaxKMeansIterationPerRun, double agglomerativeThreshold, Preprocessing preprocessor, - boolean enabled, ClusteringAlgorithm algorithm, InterClusterSimilarity agglomerativeInterClusterSimilarity, double preprocessorThreshold, - double preprocessorPercentile) { +public record ClusteringOptions(@JsonProperty("metric") SimilarityMetric similarityMetric, + @JsonProperty("spectral_bandwidth") double spectralKernelBandwidth, + @JsonProperty("spectral_gaussian_variance") double spectralGaussianProcessVariance, @JsonProperty("spectral_min_runs") int spectralMinRuns, + @JsonProperty("spectral_max_runs") int spectralMaxRuns, @JsonProperty("spectral_max_kmeans_iterations") int spectralMaxKMeansIterationPerRun, + @JsonProperty("agglomerative_threshold") double agglomerativeThreshold, @JsonProperty("preprocessor") Preprocessing preprocessor, + @JsonProperty("enabled") boolean enabled, @JsonProperty("algorithm") ClusteringAlgorithm algorithm, + @JsonProperty("inter_similarity") InterClusterSimilarity agglomerativeInterClusterSimilarity, + @JsonProperty("preprocessor_threshold") double preprocessorThreshold, + @JsonProperty("preprocessor_percentile") double preprocessorPercentile) { public ClusteringOptions(SimilarityMetric similarityMetric, double spectralKernelBandwidth, double spectralGaussianProcessVariance, int spectralMinRuns, int spectralMaxRuns, int spectralMaxKMeansIterationPerRun, double agglomerativeThreshold, Preprocessing preprocessor, diff --git a/core/src/main/java/de/jplag/csv/CsvDataMapper.java b/core/src/main/java/de/jplag/csv/CsvDataMapper.java new file mode 100644 index 000000000..67844a6d4 --- /dev/null +++ b/core/src/main/java/de/jplag/csv/CsvDataMapper.java @@ -0,0 +1,22 @@ +package de.jplag.csv; + +import java.util.Optional; + +/** + * Provides mappings for csv rows and optionally names for the columns. Needs to always return the same number of + * columns. + * @param The type of data that is mapped + */ +public interface CsvDataMapper { + /** + * Provides the cell values for one row + * @param value The original object + * @return The cell values + */ + String[] provideData(T value); + + /** + * @return The names of the columns if present + */ + Optional getTitleRow(); +} diff --git a/core/src/main/java/de/jplag/csv/CsvPrinter.java b/core/src/main/java/de/jplag/csv/CsvPrinter.java new file mode 100644 index 000000000..089eb4fe8 --- /dev/null +++ b/core/src/main/java/de/jplag/csv/CsvPrinter.java @@ -0,0 +1,144 @@ +package de.jplag.csv; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; + +import de.jplag.util.FileUtils; + +/** + * Prints a csv according to the specification in + * .... If you need to deviate from this + * definition slightly you can modify the line end and separator characters. + * @param + */ +public class CsvPrinter { + private static final char DEFAULT_SEPARATOR = ','; + private static final String DEFAULT_LINE_END = "\r\n"; // not System.lineSeparator(), because of csv specification + private static final char LITERAL = '"'; + + private final CsvDataMapper dataSource; + private final List data; + + private char separator; + private String lineEnd; + + /** + * @param dataSource The data source used to map the given object to rows. + */ + public CsvPrinter(CsvDataMapper dataSource) { + this.dataSource = dataSource; + this.data = new ArrayList<>(); + + this.separator = DEFAULT_SEPARATOR; + this.lineEnd = DEFAULT_LINE_END; + } + + /** + * Adds a new row to this csv + * @param value the value to add + */ + public void addRow(T value) { + this.data.add(this.dataSource.provideData(value)); + } + + /** + * Adds multiple rows to this csv + * @param values The values to add + */ + public void addRows(Collection values) { + values.forEach(this::addRow); + } + + /** + * Changes the separator between cells + * @param separator The new separator + */ + public void setSeparator(char separator) { + this.separator = separator; + } + + /** + * Sets the string to separate lines with + * @param lineEnd the new line end + */ + public void setLineEnd(String lineEnd) { + this.lineEnd = lineEnd; + } + + /** + * Prints this csv with all current data to a file + * @param file The file to write + * @throws IOException on io errors + */ + public void printToFile(File file) throws IOException { + try (Writer writer = FileUtils.openFileWriter(file)) { + this.printCsv(writer); + } + } + + public String printToString() throws IOException { + String csv; + + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { + try (Writer writer = new OutputStreamWriter(outputStream)) { + this.printCsv(writer); + } + + csv = outputStream.toString(); + } + + return csv; + } + + private void printCsv(Writer writer) throws IOException { + this.writeTitleRow(writer); + + for (String[] datum : this.data) { + this.printRow(writer, datum); + } + } + + private void writeTitleRow(Writer writer) throws IOException { + Optional titleRow = this.dataSource.getTitleRow(); + if (titleRow.isPresent()) { + this.printRow(writer, titleRow.get()); + } + } + + private void printRow(Writer writer, String[] data) throws IOException { + Iterator dataIterator = Arrays.stream(data).iterator(); + + if (dataIterator.hasNext()) { + printCell(writer, dataIterator.next()); + } + + while (dataIterator.hasNext()) { + writer.write(this.separator); + printCell(writer, dataIterator.next()); + } + + writer.write(this.lineEnd); + } + + private void printCell(Writer writer, String cellValue) throws IOException { + boolean literalsNeeded = cellValue.contains(String.valueOf(LITERAL)); + String actualValue = cellValue; + if (literalsNeeded) { + writer.write(LITERAL); + actualValue = actualValue.replace("\"", "\"\""); + } + writer.write(actualValue); + if (literalsNeeded) { + writer.write(LITERAL); + } + } +} diff --git a/core/src/main/java/de/jplag/csv/CsvValue.java b/core/src/main/java/de/jplag/csv/CsvValue.java new file mode 100644 index 000000000..973b60f0f --- /dev/null +++ b/core/src/main/java/de/jplag/csv/CsvValue.java @@ -0,0 +1,18 @@ +package de.jplag.csv; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Used with {@link ReflectiveCsvDataMapper} to identify fields and methods, that should be used for the csv. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD, ElementType.METHOD}) +public @interface CsvValue { + /** + * The index of the csv field. Has to be used as the compiler sometimes changes the order of fields/methods + */ + int value(); +} diff --git a/core/src/main/java/de/jplag/csv/HardcodedCsvDataMapper.java b/core/src/main/java/de/jplag/csv/HardcodedCsvDataMapper.java new file mode 100644 index 000000000..89b78edde --- /dev/null +++ b/core/src/main/java/de/jplag/csv/HardcodedCsvDataMapper.java @@ -0,0 +1,58 @@ +package de.jplag.csv; + +import java.util.Optional; +import java.util.function.Function; + +/** + * Can be used to hardcode mappings to csv. Uses the given function to map values. + * @param The mapped type. + */ +public class HardcodedCsvDataMapper implements CsvDataMapper { + private final Function mappingFunction; + private final int columnCount; + + private String[] titles; + + /** + * @param columnCount The number of columns + * @param mappingFunction The function returning the column values. Must return as many values as specified in + * columnCount + */ + public HardcodedCsvDataMapper(int columnCount, Function mappingFunction) { + this.mappingFunction = mappingFunction; + this.columnCount = columnCount; + this.titles = null; + } + + /** + * @param columnCount The number of columns + * @param mappingFunction The function returning the column values. Must return as many values as specified in + * columnCount + * @param titles The titles for the csv + */ + public HardcodedCsvDataMapper(int columnCount, Function mappingFunction, String[] titles) { + this(columnCount, mappingFunction); + this.titles = titles; + } + + @Override + public String[] provideData(T value) { + Object[] values = this.mappingFunction.apply(value); + + if (values.length != this.columnCount) { + throw new IllegalStateException("You need to return the appropriate number of columns"); + } + + String[] data = new String[this.columnCount]; + for (int i = 0; i < this.columnCount; i++) { + data[i] = String.valueOf(values[i]); + } + + return data; + } + + @Override + public Optional getTitleRow() { + return Optional.ofNullable(this.titles); + } +} diff --git a/core/src/main/java/de/jplag/csv/ReflectiveCsvDataMapper.java b/core/src/main/java/de/jplag/csv/ReflectiveCsvDataMapper.java new file mode 100644 index 000000000..1a442521f --- /dev/null +++ b/core/src/main/java/de/jplag/csv/ReflectiveCsvDataMapper.java @@ -0,0 +1,89 @@ +package de.jplag.csv; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Optional; + +import org.apache.commons.math3.util.Pair; + +/** + * Mapped data automatically based on the exposed fields and methods. + * @param The mapped type. Mark included methods and fields with @{@link CsvValue} + */ +public class ReflectiveCsvDataMapper implements CsvDataMapper { + private final List>> values; + private String[] titles; + + /** + * @param type The mapped type. + */ + public ReflectiveCsvDataMapper(Class type) { + this.values = new ArrayList<>(); + + for (Field field : type.getFields()) { + if (field.getAnnotation(CsvValue.class) != null) { + this.values.add(new Pair<>(field.getAnnotation(CsvValue.class).value(), field::get)); + } + } + + for (Method method : type.getMethods()) { + if (method.getAnnotation(CsvValue.class) != null) { + if (method.getParameters().length != 0) { + throw new IllegalStateException( + String.format("Method %s in %s must not have parameters to be a csv value", method.getName(), type.getName())); + } + if (method.getReturnType().equals(Void.class)) { + throw new IllegalStateException( + String.format("Method %s in %s must not return void to be a csv value", method.getName(), type.getName())); + } + + this.values.add(new Pair<>(method.getAnnotation(CsvValue.class).value(), method::invoke)); + } + } + + this.values.sort(Comparator.comparing(Pair::getKey)); + this.titles = null; + } + + /** + * @param type The mapped type + * @param titles The titles for the csv. Must be as many as @{@link CsvValue} annotation in the given type. + */ + public ReflectiveCsvDataMapper(Class type, String[] titles) { + this(type); + + if (this.values.size() != titles.length) { + throw new IllegalArgumentException("Csv data must have the same number of tiles and values per row."); + } + + this.titles = titles; + } + + @Override + public String[] provideData(T value) { + String[] data = new String[this.values.size()]; + + for (int i = 0; i < data.length; i++) { + try { + data[i] = String.valueOf(this.values.get(i).getValue().get(value)); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new IllegalStateException(e); + } + } + + return data; + } + + @Override + public Optional getTitleRow() { + return Optional.ofNullable(this.titles); + } + + private interface GetterFunction { + Object get(T instance) throws IllegalAccessException, InvocationTargetException; + } +} diff --git a/core/src/main/java/de/jplag/csv/comparisons/CsvComparisonData.java b/core/src/main/java/de/jplag/csv/comparisons/CsvComparisonData.java new file mode 100644 index 000000000..b275d840a --- /dev/null +++ b/core/src/main/java/de/jplag/csv/comparisons/CsvComparisonData.java @@ -0,0 +1,14 @@ +package de.jplag.csv.comparisons; + +import de.jplag.csv.CsvValue; + +/** + * Comparison data for writing to a csv. + * @param firstSubmissionName The name of the first submission + * @param secondSubmissionName The name of the second submission + * @param averageSimilarity The average similarity + * @param maxSimilarity The maximum similarity + */ +public record CsvComparisonData(@CsvValue(1) String firstSubmissionName, @CsvValue(2) String secondSubmissionName, + @CsvValue(3) double averageSimilarity, @CsvValue(4) double maxSimilarity) { +} diff --git a/core/src/main/java/de/jplag/csv/comparisons/CsvComparisonOutput.java b/core/src/main/java/de/jplag/csv/comparisons/CsvComparisonOutput.java new file mode 100644 index 000000000..013ee2f7b --- /dev/null +++ b/core/src/main/java/de/jplag/csv/comparisons/CsvComparisonOutput.java @@ -0,0 +1,61 @@ +package de.jplag.csv.comparisons; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import de.jplag.JPlagComparison; +import de.jplag.csv.CsvDataMapper; +import de.jplag.csv.CsvPrinter; +import de.jplag.csv.HardcodedCsvDataMapper; +import de.jplag.csv.ReflectiveCsvDataMapper; +import de.jplag.options.SimilarityMetric; + +/** + * Frontend for writing the result comparisons as a csv. + */ +public class CsvComparisonOutput { + private static final String[] titles = new String[] {"submissionName1", "submissionName2", "averageSimilarity", "maxSimilarity"}; + + private CsvComparisonOutput() { + } + + /** + * Writes the comparisons as a csv + * @param comparisons The list of comparisons + * @param anonymize If true only random ids will be printed and an additional file will contain the actual names + * @param directory The directory to write into + * @param fileName The base name for the file without ".csv" + */ + public static void writeCsvResults(List comparisons, boolean anonymize, File directory, String fileName) throws IOException { + NameMapper mapper = new NameMapper.IdentityMapper(); + directory.mkdirs(); + + if (anonymize) { + mapper = new NameMapperIncrementalIds(); + } + + CsvDataMapper dataMapper = new ReflectiveCsvDataMapper<>(CsvComparisonData.class, titles); + CsvPrinter printer = new CsvPrinter<>(dataMapper); + + for (JPlagComparison comparison : comparisons) { + double average = SimilarityMetric.AVG.applyAsDouble(comparison); + double max = SimilarityMetric.MAX.applyAsDouble(comparison); + String firstName = mapper.map(comparison.firstSubmission().getName()); + String secondName = mapper.map(comparison.secondSubmission().getName()); + printer.addRow(new CsvComparisonData(firstName, secondName, average, max)); + } + + printer.printToFile(new File(directory, fileName + ".csv")); + + if (anonymize) { + List> nameMap = mapper.getNameMap(); + CsvDataMapper> namesMapMapper = new HardcodedCsvDataMapper<>(2, it -> new String[] {it.getValue(), it.getKey()}, + new String[] {"id", "realName"}); + CsvPrinter> namesPrinter = new CsvPrinter<>(namesMapMapper); + namesPrinter.addRows(nameMap); + namesPrinter.printToFile(new File(directory, fileName + "-names.csv")); + } + } +} diff --git a/core/src/main/java/de/jplag/csv/comparisons/NameMapper.java b/core/src/main/java/de/jplag/csv/comparisons/NameMapper.java new file mode 100644 index 000000000..d514eef5d --- /dev/null +++ b/core/src/main/java/de/jplag/csv/comparisons/NameMapper.java @@ -0,0 +1,37 @@ +package de.jplag.csv.comparisons; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * Maps the names of submissions for csv printing. Used to anonymize data if needed. + */ +public interface NameMapper { + /** + * Maps the original name to the one that should be printed. + * @param original The original name + * @return The name for printing + */ + String map(String original); + + /** + * @return The list of mappings. + */ + List> getNameMap(); + + /** + * Simple implementation, that does not change the names. + */ + class IdentityMapper implements NameMapper { + @Override + public String map(String original) { + return original; + } + + @Override + public List> getNameMap() { + return Collections.emptyList(); + } + } +} diff --git a/core/src/main/java/de/jplag/csv/comparisons/NameMapperIncrementalIds.java b/core/src/main/java/de/jplag/csv/comparisons/NameMapperIncrementalIds.java new file mode 100644 index 000000000..c3e0aaa29 --- /dev/null +++ b/core/src/main/java/de/jplag/csv/comparisons/NameMapperIncrementalIds.java @@ -0,0 +1,42 @@ +package de.jplag.csv.comparisons; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Maps the real names of submissions to incremental ids. The ids will be in order of the queried new names. + */ +public class NameMapperIncrementalIds implements NameMapper { + private final Map map; + private int nextId; + + /** + * New instance + */ + public NameMapperIncrementalIds() { + this.map = new HashMap<>(); + this.nextId = 0; + } + + private String newId() { + String id = String.valueOf(this.nextId++); + + if (this.map.containsKey(id)) { + return newId(); + } + + return id; + } + + @Override + public String map(String original) { + this.map.computeIfAbsent(original, ignore -> this.newId()); + return this.map.get(original); + } + + @Override + public List> getNameMap() { + return this.map.entrySet().stream().toList(); + } +} diff --git a/core/src/main/java/de/jplag/logging/ProgressBar.java b/core/src/main/java/de/jplag/logging/ProgressBar.java new file mode 100644 index 000000000..04450434a --- /dev/null +++ b/core/src/main/java/de/jplag/logging/ProgressBar.java @@ -0,0 +1,24 @@ +package de.jplag.logging; + +/** + * Exposed interactions for a running progress bar. + */ +public interface ProgressBar { + /** + * Advances the progress bar by a single step + */ + default void step() { + step(1); + } + + /** + * Advances the progress bar by amount steps + * @param number The number of steps + */ + void step(int number); + + /** + * Closes the progress bar. After this method has been called the behaviour of the other methods is undefined. + */ + void dispose(); +} diff --git a/core/src/main/java/de/jplag/logging/ProgressBarLogger.java b/core/src/main/java/de/jplag/logging/ProgressBarLogger.java new file mode 100644 index 000000000..889d391bb --- /dev/null +++ b/core/src/main/java/de/jplag/logging/ProgressBarLogger.java @@ -0,0 +1,68 @@ +package de.jplag.logging; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Provides static access to the creation of progress bars. + */ +public class ProgressBarLogger { + private static ProgressBarProvider progressBarProvider = new DummyProvider(); + + private ProgressBarLogger() { + // Hides default constructor + } + + /** + * Creates a new {@link ProgressBar} + * @param type The type of the progress bar + * @param totalSteps The total number of steps + * @return The newly created progress bar + */ + public static ProgressBar createProgressBar(ProgressBarType type, int totalSteps) { + return progressBarProvider.initProgressBar(type, totalSteps); + } + + /** + * Sets the {@link ProgressBarProvider}. Should be used by the ui before calling JPlag, if progress bars should be + * shown. + * @param progressBarProvider The provider + */ + public static void setProgressBarProvider(ProgressBarProvider progressBarProvider) { + ProgressBarLogger.progressBarProvider = progressBarProvider; + } + + private static class DummyProvider implements ProgressBarProvider { + @Override + public ProgressBar initProgressBar(ProgressBarType type, int totalSteps) { + return new DummyBar(type, totalSteps); + } + } + + private static class DummyBar implements ProgressBar { + private static final Logger logger = LoggerFactory.getLogger(DummyBar.class); + private int currentStep; + + public DummyBar(ProgressBarType type, int totalSteps) { + this.currentStep = 0; + logger.info("{} ({})", type.getDefaultText(), totalSteps); + } + + @Override + public void step() { + logger.info("Now at step {}", this.currentStep++); + } + + @Override + public void step(int number) { + for (int i = 0; i < number; i++) { + step(); + } + } + + @Override + public void dispose() { + logger.info("Progress bar done."); + } + } +} diff --git a/core/src/main/java/de/jplag/logging/ProgressBarProvider.java b/core/src/main/java/de/jplag/logging/ProgressBarProvider.java new file mode 100644 index 000000000..13268325b --- /dev/null +++ b/core/src/main/java/de/jplag/logging/ProgressBarProvider.java @@ -0,0 +1,14 @@ +package de.jplag.logging; + +/** + * Provides the capability to create new progress bars, to allow JPlag to access the ui. + */ +public interface ProgressBarProvider { + /** + * Creates a new progress bar + * @param type The type of progress bar. Should mostly determine the name + * @param totalSteps The total number of steps the progress bar should have + * @return The newly created bar + */ + ProgressBar initProgressBar(ProgressBarType type, int totalSteps); +} diff --git a/core/src/main/java/de/jplag/logging/ProgressBarType.java b/core/src/main/java/de/jplag/logging/ProgressBarType.java new file mode 100644 index 000000000..88e520fcc --- /dev/null +++ b/core/src/main/java/de/jplag/logging/ProgressBarType.java @@ -0,0 +1,23 @@ +package de.jplag.logging; + +/** + * The available processes. Used as a hint for the ui, which step JPlag is currently performing. + */ +public enum ProgressBarType { + LOADING("Loading Submissions "), + PARSING("Parsing Submissions "), + COMPARING("Comparing Submissions"); + + private final String defaultText; + + ProgressBarType(String defaultText) { + this.defaultText = defaultText; + } + + /** + * @return The default display text for the type + */ + public String getDefaultText() { + return defaultText; + } +} 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..3067e32a6 --- /dev/null +++ b/core/src/main/java/de/jplag/merging/MatchMerging.java @@ -0,0 +1,192 @@ +package de.jplag.merging; + +import java.util.ArrayList; +import java.util.Comparator; +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 final 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 = mergeNeighbors(globalMatches, leftSubmission, rightSubmission); + globalMatches = globalMatches.stream().filter(it -> it.length() >= options.minimumTokenMatch()).toList(); + 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); + List sortedByRight = new ArrayList<>(globalMatches); + + sortedByLeft.sort(Comparator.comparingInt(Match::startOfFirst)); + sortedByRight.sort(Comparator.comparingInt(Match::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; + } +} \ 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..7d77f7f31 --- /dev/null +++ b/core/src/main/java/de/jplag/merging/MergingOptions.java @@ -0,0 +1,51 @@ +package de.jplag.merging; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * 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(@JsonProperty("enabled") boolean enabled, @JsonProperty("min_neighbour_length") int minimumNeighborLength, + @JsonProperty("max_gap_size") int maximumGapSize) { + + public static final boolean DEFAULT_ENABLED = false; + public static final int DEFAULT_NEIGHBOR_LENGTH = 2; + public static final int DEFAULT_GAP_SIZE = 6; + + /** + * 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(DEFAULT_ENABLED, DEFAULT_NEIGHBOR_LENGTH, DEFAULT_GAP_SIZE); + } + + /** + * 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..b10fda2ea --- /dev/null +++ b/core/src/main/java/de/jplag/normalization/MultipleEdge.java @@ -0,0 +1,38 @@ +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 final 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..ace0d1ba3 --- /dev/null +++ b/core/src/main/java/de/jplag/normalization/NormalizationGraphConstructor.java @@ -0,0 +1,139 @@ +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 final SimpleDirectedGraph graph; + private int bidirectionalBlockDepth; + private final Collection fullPositionSignificanceIncoming; + private Statement lastFullPositionSignificance; + private Statement lastPartialPositionSignificance; + private final Map> variableReads; + private final Map> variableWrites; + private final 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..a749a5774 --- /dev/null +++ b/core/src/main/java/de/jplag/normalization/Statement.java @@ -0,0 +1,78 @@ +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..eef5d0c82 --- /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 final 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..5ece0ff1f --- /dev/null +++ b/core/src/main/java/de/jplag/normalization/TokenStringNormalizer.java @@ -0,0 +1,78 @@ +package de.jplag.normalization; + +import java.util.ArrayList; +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 sequence normalization. + */ +public class TokenStringNormalizer { + + private TokenStringNormalizer() { + } + + /** + * Performs token sequence normalization. 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 sequence. + * @param tokens The original token sequence, remains unaltered. + * @return The normalized token sequence. + */ + public static List normalize(List tokens) { + SimpleDirectedGraph normalizationGraph = new NormalizationGraphConstructor(tokens).get(); + List normalizedTokens = new ArrayList<>(tokens.size()); + 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()) { + normalizedTokens.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; + } + return normalizedTokens; + } + + /** + * 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..6d7067748 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,12 @@ import de.jplag.Language; import de.jplag.clustering.ClusteringOptions; import de.jplag.exceptions.BasecodeException; +import de.jplag.merging.MergingOptions; +import de.jplag.reporting.jsonfactory.serializer.LanguageSerializer; +import de.jplag.util.FileUtils; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; /** * This record defines the options to configure {@link JPlag}. @@ -44,28 +49,33 @@ * @param clusteringOptions Clustering options * @param debugParser If true, submissions that cannot be parsed will be stored in a separate directory. */ -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) { +public record JPlagOptions(@JsonSerialize(using = LanguageSerializer.class) Language language, + @JsonProperty("min_token_match") Integer minimumTokenMatch, @JsonProperty("submission_directories") Set submissionDirectories, + @JsonProperty("old_directories") Set oldSubmissionDirectories, @JsonProperty("base_directory") File baseCodeSubmissionDirectory, + @JsonProperty("subdirectory_name") String subdirectoryName, @JsonProperty("file_suffixes") List fileSuffixes, + @JsonProperty("exclusion_file_name") String exclusionFileName, @JsonProperty("similarity_metric") SimilarityMetric similarityMetric, + @JsonProperty("similarity_threshold") double similarityThreshold, @JsonProperty("max_comparisons") int maximumNumberOfComparisons, + @JsonProperty("cluster") ClusteringOptions clusteringOptions, boolean debugParser, @JsonProperty("merging") MergingOptions mergingOptions, + @JsonProperty("normalize") boolean normalize) { public static final double DEFAULT_SIMILARITY_THRESHOLD = 0; - public static final int DEFAULT_SHOWN_COMPARISONS = 100; + public static final int DEFAULT_SHOWN_COMPARISONS = 500; 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(), false); } 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, boolean normalize) { this.language = language; this.debugParser = debugParser; this.fileSuffixes = fileSuffixes == null || fileSuffixes.isEmpty() ? null : Collections.unmodifiableList(fileSuffixes); @@ -79,84 +89,98 @@ public JPlagOptions(Language language, Integer minimumTokenMatch, Set subm this.baseCodeSubmissionDirectory = baseCodeSubmissionDirectory; this.subdirectoryName = subdirectoryName; this.clusteringOptions = clusteringOptions; + this.mergingOptions = mergingOptions; + this.normalize = normalize; } public JPlagOptions withLanguageOption(Language language) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions, normalize); } public JPlagOptions withDebugParser(boolean debugParser) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions, normalize); } public JPlagOptions withFileSuffixes(List fileSuffixes) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions, normalize); } public JPlagOptions withSimilarityThreshold(double similarityThreshold) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions, normalize); } public JPlagOptions withMaximumNumberOfComparisons(int maximumNumberOfComparisons) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions, normalize); } public JPlagOptions withSimilarityMetric(SimilarityMetric similarityMetric) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions, normalize); } public JPlagOptions withMinimumTokenMatch(Integer minimumTokenMatch) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions, normalize); } public JPlagOptions withExclusionFileName(String exclusionFileName) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions, normalize); } public JPlagOptions withSubmissionDirectories(Set submissionDirectories) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions, normalize); } public JPlagOptions withOldSubmissionDirectories(Set oldSubmissionDirectories) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions, normalize); } public JPlagOptions withBaseCodeSubmissionDirectory(File baseCodeSubmissionDirectory) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions, normalize); } public JPlagOptions withSubdirectoryName(String subdirectoryName) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions, normalize); } public JPlagOptions withClusteringOptions(ClusteringOptions clusteringOptions) { return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, - clusteringOptions, debugParser); + clusteringOptions, debugParser, mergingOptions, normalize); + } + + public JPlagOptions withMergingOptions(MergingOptions mergingOptions) { + return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, + subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, + clusteringOptions, debugParser, mergingOptions, normalize); + } + + public JPlagOptions withNormalize(boolean normalize) { + return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionDirectory, + subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons, + clusteringOptions, debugParser, mergingOptions, normalize); } public boolean hasBaseCode() { @@ -170,21 +194,23 @@ public Set excludedFiles() { @Override public List fileSuffixes() { var language = language(); - if ((fileSuffixes == null || fileSuffixes.isEmpty()) && language != null) + if ((fileSuffixes == null || fileSuffixes.isEmpty()) && language != null) { return Arrays.stream(language.suffixes()).toList(); + } return fileSuffixes == null ? null : Collections.unmodifiableList(fileSuffixes); } @Override public Integer minimumTokenMatch() { var language = language(); - if (minimumTokenMatch == null && language != null) + if (minimumTokenMatch == null && language != null) { return language.minimumTokenMatch(); + } return 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)); @@ -200,7 +226,8 @@ private static double normalizeSimilarityThreshold(double similarityThreshold) { if (similarityThreshold > 1) { logger.warn("Maximum threshold of 1 used instead of {}", similarityThreshold); return 1; - } else if (similarityThreshold < 0) { + } + if (similarityThreshold < 0) { logger.warn("Minimum threshold of 0 used instead of {}", similarityThreshold); return 0; } else { @@ -245,10 +272,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, false); } /** @@ -271,7 +298,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()); } @@ -289,23 +316,18 @@ private static File convertLegacyBaseCodeToFile(String baseCodeSubmissionName, F File baseCodeAsAbsolutePath = new File(baseCodeSubmissionName); if (baseCodeAsAbsolutePath.exists()) { return baseCodeAsAbsolutePath; - } else { - String normalizedName = baseCodeSubmissionName; - while (normalizedName.startsWith(File.separator)) { - normalizedName = normalizedName.substring(1); - } - 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(".")) { - throw new BasecodeException( - "The basecode directory name \"" + normalizedName + "\" cannot contain dots! Please migrate to the path-based API."); - } - return new File(submissionDirectory, baseCodeSubmissionName); } + String normalizedName = baseCodeSubmissionName; + while (normalizedName.startsWith(File.separator)) { + normalizedName = normalizedName.substring(1); + } + while (normalizedName.endsWith(File.separator)) { + normalizedName = normalizedName.substring(0, normalizedName.length() - 1); + } + 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."); + } + return new File(submissionDirectory, baseCodeSubmissionName); } } 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..aff67ef3e --- /dev/null +++ b/core/src/main/java/de/jplag/reporting/FilePathUtil.java @@ -0,0 +1,50 @@ +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 static final String ZIP_PATH_SEPARATOR = "/"; // Paths in zip files are always separated by a slash + private static final String WINDOWS_PATH_SEPARATOR = "\\"; + + 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(); + } + + /** + * Joins logical paths using a slash. This method ensures, that no duplicate slashes are created in between. + * @param left The left path segment + * @param right The right path segment + * @return The joined paths + */ + public static String joinZipPathSegments(String left, String right) { + String rightStripped = right; + while (rightStripped.startsWith(ZIP_PATH_SEPARATOR) || rightStripped.startsWith(WINDOWS_PATH_SEPARATOR)) { + rightStripped = rightStripped.substring(1); + } + + String leftStripped = left; + while (leftStripped.endsWith(ZIP_PATH_SEPARATOR) || leftStripped.startsWith(WINDOWS_PATH_SEPARATOR)) { + leftStripped = leftStripped.substring(0, leftStripped.length() - 1); + } + + return leftStripped + ZIP_PATH_SEPARATOR + rightStripped; + } +} 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..29f93744c 100644 --- a/core/src/main/java/de/jplag/reporting/jsonfactory/ComparisonReportWriter.java +++ b/core/src/main/java/de/jplag/reporting/jsonfactory/ComparisonReportWriter.java @@ -1,7 +1,5 @@ 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; @@ -13,8 +11,11 @@ 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; +import de.jplag.reporting.reportobject.writer.JPlagResultWriter; /** * Writes {@link ComparisonReport}s of given {@link JPlagResult} to the disk under the specified path. Instantiated with @@ -22,43 +23,43 @@ */ public class ComparisonReportWriter { - private final FileWriter fileWriter; + private final JPlagResultWriter resultWriter; private final Function submissionToIdFunction; private final Map> submissionIdToComparisonFileName = new ConcurrentHashMap<>(); private final Map fileNameCollisions = new ConcurrentHashMap<>(); - public ComparisonReportWriter(Function submissionToIdFunction, FileWriter fileWriter) { + public ComparisonReportWriter(Function submissionToIdFunction, JPlagResultWriter resultWriter) { this.submissionToIdFunction = submissionToIdFunction; - this.fileWriter = fileWriter; + this.resultWriter = resultWriter; } /** * Generates detailed ComparisonReport DTO for each comparison in a JPlagResult and writes them to the disk as json * files. * @param jPlagResult The JPlagResult to generate the comparison reports from. contains information about a comparison - * @param path The path to write the comparison files to * @return Nested map that associates each pair of submissions (by their ids) to their comparison file name. The * comparison file name for submission with id id1 and id2 can be fetched by executing get two times: * map.get(id1).get(id2). The nested map is symmetrical therefore, both map.get(id1).get(id2) and map.get(id2).get(id1) * yield the same result. */ - public Map> writeComparisonReports(JPlagResult jPlagResult, String path) { + public Map> writeComparisonReports(JPlagResult jPlagResult) { int numberOfComparisons = jPlagResult.getOptions().maximumNumberOfComparisons(); List comparisons = jPlagResult.getComparisons(numberOfComparisons); - writeComparisons(path, comparisons); + writeComparisons(comparisons); return submissionIdToComparisonFileName; } - private void writeComparisons(String path, List comparisons) { - comparisons.parallelStream().forEach(comparison -> { + private void writeComparisons(List comparisons) { + for (JPlagComparison comparison : comparisons) { String firstSubmissionId = submissionToIdFunction.apply(comparison.firstSubmission()); String secondSubmissionId = submissionToIdFunction.apply(comparison.secondSubmission()); String fileName = generateComparisonName(firstSubmissionId, secondSubmissionId); addToLookUp(firstSubmissionId, secondSubmissionId, fileName); - var comparisonReport = new ComparisonReport(firstSubmissionId, secondSubmissionId, comparison.similarity(), - convertMatchesToReportMatches(comparison)); - fileWriter.saveAsJSON(comparisonReport, path, fileName); - }); + var comparisonReport = new ComparisonReport(firstSubmissionId, secondSubmissionId, + Map.of(SimilarityMetric.AVG.name(), comparison.similarity(), SimilarityMetric.MAX.name(), comparison.maximalSimilarity()), + convertMatchesToReportMatches(comparison), comparison.similarityOfFirst(), comparison.similarityOfSecond()); + resultWriter.addJsonEntry(comparisonReport, fileName); + } } private void addToLookUp(String firstSubmissionId, String secondSubmissionId, String fileName) { @@ -96,23 +97,16 @@ private Match convertMatchToReportMatch(JPlagComparison comparison, de.jplag.Mat List tokensFirst = comparison.firstSubmission().getTokenList().subList(match.startOfFirst(), match.endOfFirst() + 1); List tokensSecond = comparison.secondSubmission().getTokenList().subList(match.startOfSecond(), match.endOfSecond() + 1); - Comparator lineComparator = (first, second) -> first.getLine() - second.getLine(); + Comparator lineComparator = Comparator.comparingInt(Token::getLine); Token startOfFirst = tokensFirst.stream().min(lineComparator).orElseThrow(); Token endOfFirst = tokensFirst.stream().max(lineComparator).orElseThrow(); 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()); - } - - 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()); } } diff --git a/core/src/main/java/de/jplag/reporting/jsonfactory/DirectoryManager.java b/core/src/main/java/de/jplag/reporting/jsonfactory/DirectoryManager.java deleted file mode 100644 index 8bbe60593..000000000 --- a/core/src/main/java/de/jplag/reporting/jsonfactory/DirectoryManager.java +++ /dev/null @@ -1,121 +0,0 @@ -package de.jplag.reporting.jsonfactory; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.Comparator; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Provides Methods for creating directories. - */ -public class DirectoryManager { - private static final Logger logger = LoggerFactory.getLogger(DirectoryManager.class); - - /** - * Creates a full path directory. - * @param path The path under which the new directory or file ought to be created - * @param name The name of the new directory. According to this name we can get sub-folder's structure after this - * directory. - * @param file The file, which has the path of sub-folders - * @param submissionRoot The file, which has the root path of submission - * @return The created directory which has the whole structure as file - */ - public static File createDirectory(String path, String name, File file, File submissionRoot) throws IOException { - File directory; - String fileFullPath = file.getPath(); - String submissionRootPath = submissionRoot.getPath(); - String filePathWithoutRootName = fileFullPath.substring(submissionRootPath.length()); - String outputRootDirectory = Path.of(path, name).toString(); - if ("".equals(filePathWithoutRootName)) { - directory = new File(Path.of(outputRootDirectory, name).toString()); - } else { - directory = new File(outputRootDirectory + filePathWithoutRootName); - } - if (!directory.exists() && !directory.mkdirs()) { - throw new IOException("Failed to create dir."); - } - return directory; - } - - /** - * Creates a directory. - * @param path The path under which the new directory ought to be created - * @param name The name of the new directory - * @return The created directory - */ - public static File createDirectory(String path, String name) throws IOException { - File directory = new File(path.concat(File.separator).concat(name)); - if (!directory.exists() && !directory.mkdirs()) { - throw new IOException("Failed to create dir."); - } - return directory; - } - - /** - * Create a directory with the given path - * @param path The path of the new directory - */ - public static void createDirectory(String path) throws IOException { - createDirectory(path, ""); - } - - /** - * Delete the directory and all of its contents, identified by the given path - * @param path The path that identifies the directory to delete - */ - public static void deleteDirectory(String path) { - try (var f = Files.walk(Path.of(path))) { - f.sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete); - } catch (IOException e) { - logger.error("Could not delete folder " + path, e); - } - } - - /** - * Zip the directory identified by the given path - * @param path The path that identifies the directory to zip - * @return True if zip was successful, false otherwise - */ - public static boolean zipDirectory(String path) { - Path p = Path.of(path); - String zipName = path + ".zip"; - - try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipName))) { - - Files.walkFileTree(p, new SimpleFileVisitor<>() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - Path targetFile = p.relativize(file); - zos.putNextEntry(new ZipEntry(targetFile.toString())); - - byte[] bytes = Files.readAllBytes(file); - zos.write(bytes, 0, bytes.length); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { - logger.error("Unable to zip " + file, exc); - throw exc; - } - }); - } catch (IOException e) { - logger.error(e.getMessage(), e); - deleteDirectory(zipName); - return false; - } - logger.info("Successfully zipped report files: {}", zipName); - logger.info("Display the results with the report viewer at https://jplag.github.io/JPlag/"); - return true; - } -} diff --git a/core/src/main/java/de/jplag/reporting/jsonfactory/DummyWriter.java b/core/src/main/java/de/jplag/reporting/jsonfactory/DummyWriter.java deleted file mode 100644 index 7f8841fc9..000000000 --- a/core/src/main/java/de/jplag/reporting/jsonfactory/DummyWriter.java +++ /dev/null @@ -1,13 +0,0 @@ -package de.jplag.reporting.jsonfactory; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class DummyWriter implements FileWriter { - private static final Logger logger = LoggerFactory.getLogger(DummyWriter.class); - - @Override - public void saveAsJSON(Object fileToSave, String folderPath, String fileName) { - logger.info("DummyWriter writes object " + fileToSave + " to path " + folderPath + " with name " + fileName + " as JSON."); - } -} diff --git a/core/src/main/java/de/jplag/reporting/jsonfactory/FileWriter.java b/core/src/main/java/de/jplag/reporting/jsonfactory/FileWriter.java deleted file mode 100644 index e0198684b..000000000 --- a/core/src/main/java/de/jplag/reporting/jsonfactory/FileWriter.java +++ /dev/null @@ -1,5 +0,0 @@ -package de.jplag.reporting.jsonfactory; - -public interface FileWriter { - void saveAsJSON(Object fileToSave, String folderPath, String fileName); -} diff --git a/core/src/main/java/de/jplag/reporting/jsonfactory/ToDiskWriter.java b/core/src/main/java/de/jplag/reporting/jsonfactory/ToDiskWriter.java deleted file mode 100644 index 48722e6b1..000000000 --- a/core/src/main/java/de/jplag/reporting/jsonfactory/ToDiskWriter.java +++ /dev/null @@ -1,30 +0,0 @@ -package de.jplag.reporting.jsonfactory; - -import java.io.IOException; -import java.nio.file.Path; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.fasterxml.jackson.databind.ObjectMapper; - -public class ToDiskWriter implements FileWriter { - private static final Logger logger = LoggerFactory.getLogger(ToDiskWriter.class); - - private static final ObjectMapper objectMapper = new ObjectMapper(); - - /** - * Saves the provided object to the provided path under the provided name - * @param fileToSave The object to save - * @param folderPath The path to save the object to - * @param fileName The name to save the object under - */ - @Override - public void saveAsJSON(Object fileToSave, String folderPath, String fileName) { - try { - objectMapper.writeValue(Path.of(folderPath, fileName).toFile(), fileToSave); - } catch (IOException e) { - logger.error("Failed to save json file " + fileName + ": " + e.getMessage(), e); - } - } -} diff --git a/core/src/main/java/de/jplag/reporting/jsonfactory/serializer/LanguageSerializer.java b/core/src/main/java/de/jplag/reporting/jsonfactory/serializer/LanguageSerializer.java new file mode 100644 index 000000000..c521507c7 --- /dev/null +++ b/core/src/main/java/de/jplag/reporting/jsonfactory/serializer/LanguageSerializer.java @@ -0,0 +1,32 @@ +package de.jplag.reporting.jsonfactory.serializer; + +import java.io.IOException; +import java.io.Serial; + +import de.jplag.Language; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; + +public class LanguageSerializer extends StdSerializer { + + @Serial + private static final long serialVersionUID = 5944655736767387268L; // generated + + /** + * Constructor used by the fasterxml.jackson + */ + public LanguageSerializer() { + this(null); + } + + public LanguageSerializer(Class languageClass) { + super(languageClass); + } + + @Override + public void serialize(Language language, JsonGenerator generator, SerializerProvider provider) throws IOException { + generator.writeString(language.getName()); + } +} 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..d569a5252 100644 --- a/core/src/main/java/de/jplag/reporting/reportobject/ReportObjectFactory.java +++ b/core/src/main/java/de/jplag/reporting/reportobject/ReportObjectFactory.java @@ -1,17 +1,13 @@ package de.jplag.reporting.reportobject; -import static de.jplag.reporting.jsonfactory.DirectoryManager.createDirectory; -import static de.jplag.reporting.jsonfactory.DirectoryManager.deleteDirectory; -import static de.jplag.reporting.jsonfactory.DirectoryManager.zipDirectory; import static de.jplag.reporting.reportobject.mapper.SubmissionNameToIdMapper.buildSubmissionNameToIdMap; import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; +import java.io.FileNotFoundException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -26,13 +22,17 @@ import de.jplag.JPlagResult; import de.jplag.Language; import de.jplag.Submission; +import de.jplag.options.JPlagOptions; +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.SubmissionFile; +import de.jplag.reporting.reportobject.model.SubmissionFileIndex; import de.jplag.reporting.reportobject.model.Version; +import de.jplag.reporting.reportobject.writer.JPlagResultWriter; +import de.jplag.reporting.reportobject.writer.ZipWriter; /** * Factory class, responsible for converting a JPlagResult object to Overview and Comparison DTO classes and writing it @@ -41,47 +41,58 @@ public class ReportObjectFactory { 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 README_FILE_NAME = "README.txt"; + public static final String OPTIONS_FILE_NAME = "options.json"; + private static final String[] README_CONTENT = new String[] {"This is a software plagiarism report generated by JPlag.", + "To view the report go to https://jplag.github.io/JPlag/ and drag the generated zip file onto the page."}; + + public static final String SUBMISSION_FILE_INDEX_FILE_NAME = "submissionFileIndex.json"; public static final Version REPORT_VIEWER_VERSION = JPlag.JPLAG_VERSION; + private static final String SUBMISSIONS_ROOT_PATH = "files/"; + private Map submissionNameToIdMap; private Function submissionToIdFunction; private Map> submissionNameToNameToComparisonFileName; + private final JPlagResultWriter resultWriter; + /** - * Creates all necessary report viewer files, writes them to the disk as zip. - * @param result The JPlagResult to be converted into a report. - * @param path The Path to save the report to + * Creates a new report object factory, that can be used to write a report. + * @param resultWriter The writer to use for writing report content */ - public void createAndSaveReport(JPlagResult result, String path) { - - try { - logger.info("Start writing report files..."); - createDirectory(path); - buildSubmissionToIdMap(result); + public ReportObjectFactory(JPlagResultWriter resultWriter) { + this.resultWriter = resultWriter; + } - copySubmissionFilesToReport(path, result); + /** + * Creates a new report object factory, that can be used to write a zip report. + * @param zipFile The zip file to write the report to + * @throws FileNotFoundException If the file cannot be opened for writing + */ + public ReportObjectFactory(File zipFile) throws FileNotFoundException { + this(new ZipWriter(zipFile)); + } - writeComparisons(result, path); - writeOverview(result, path); + /** + * Creates all necessary report viewer files, writes them to the disk as zip. + * @param result The JPlagResult to be converted into a report. + */ + public void createAndSaveReport(JPlagResult result) { + logger.info("Start writing report..."); + buildSubmissionToIdMap(result); - logger.info("Zipping report files..."); - zipAndDelete(path); - } catch (IOException e) { - logger.error("Could not create directory " + path + " for report viewer generation", e); - } + copySubmissionFilesToReport(result); - } + writeComparisons(result); + writeOverview(result); + writeSubmissionIndexFile(result); + writeReadMeFile(); + writeOptionsFiles(result.getOptions()); - private void zipAndDelete(String path) { - boolean zipWasSuccessful = zipDirectory(path); - if (zipWasSuccessful) { - deleteDirectory(path); - } else { - logger.error("Could not zip results. The results are still available uncompressed at " + path); - } + this.resultWriter.close(); } private void buildSubmissionToIdMap(JPlagResult result) { @@ -89,61 +100,23 @@ private void buildSubmissionToIdMap(JPlagResult result) { submissionToIdFunction = (Submission submission) -> submissionNameToIdMap.get(submission.getName()); } - private void copySubmissionFilesToReport(String path, JPlagResult result) { - logger.info("Start copying submission files to the output directory..."); + private void copySubmissionFilesToReport(JPlagResult result) { + logger.info("Start to export results..."); List comparisons = result.getComparisons(result.getOptions().maximumNumberOfComparisons()); Set submissions = getSubmissions(comparisons); - File submissionsPath = createSubmissionsDirectory(path); - if (submissionsPath == null) { - return; - } Language language = result.getOptions().language(); for (Submission submission : submissions) { - File directory = createSubmissionDirectory(path, submissionsPath, submission); - File submissionRoot = submission.getRoot(); - if (directory == null) { - continue; - } + String submissionRootPath = SUBMISSIONS_ROOT_PATH + submissionToIdFunction.apply(submission); for (File file : submission.getFiles()) { - File fullPath = createSubmissionDirectory(path, submissionsPath, submission, file, submissionRoot); - File fileToCopy = getFileToCopy(language, file); - try { - if (fullPath != null) { - Files.copy(fileToCopy.toPath(), fullPath.toPath(), StandardCopyOption.REPLACE_EXISTING); - } else { - throw new NullPointerException("Could not create file with full path"); - } - } catch (IOException e) { - logger.error("Could not save submission file " + fileToCopy, e); + String relativeFilePath = file.getAbsolutePath().substring(submission.getRoot().getAbsolutePath().length()); + if (relativeFilePath.isEmpty()) { + relativeFilePath = file.getName(); } - } - } - } + String zipPath = FilePathUtil.joinZipPathSegments(submissionRootPath, relativeFilePath); - private File createSubmissionDirectory(String path, File submissionsPath, Submission submission, File file, File submissionRoot) { - 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); - return null; - } - } - - private File createSubmissionDirectory(String path, File submissionsPath, Submission submission) { - try { - return createDirectory(submissionsPath.getPath(), submissionToIdFunction.apply(submission)); - } catch (IOException e) { - logger.error("Could not create directory " + path + " for report viewer generation", e); - return null; - } - } - - 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); - return null; + File fileToCopy = getFileToCopy(language, file); + this.resultWriter.addFileContentEntry(zipPath, fileToCopy); + } } } @@ -151,13 +124,12 @@ private File getFileToCopy(Language language, File file) { return language.useViewFiles() ? new File(file.getPath() + language.viewFileSuffix()) : file; } - private void writeComparisons(JPlagResult result, String path) { - ComparisonReportWriter comparisonReportWriter = new ComparisonReportWriter(submissionToIdFunction, fileWriter); - submissionNameToNameToComparisonFileName = comparisonReportWriter.writeComparisonReports(result, path); + private void writeComparisons(JPlagResult result) { + ComparisonReportWriter comparisonReportWriter = new ComparisonReportWriter(submissionToIdFunction, this.resultWriter); + submissionNameToNameToComparisonFileName = comparisonReportWriter.writeComparisonReports(result); } - private void writeOverview(JPlagResult result, String path) { - + private void writeOverview(JPlagResult result) { List folders = new ArrayList<>(); folders.addAll(result.getOptions().submissionDirectories()); folders.addAll(result.getOptions().oldSubmissionDirectories()); @@ -167,7 +139,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,12 +154,39 @@ 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 - fileWriter.saveAsJSON(overviewReport, path, OVERVIEW_FILE_NAME); + this.resultWriter.addJsonEntry(overviewReport, OVERVIEW_FILE_NAME); + + } + + private void writeReadMeFile() { + this.resultWriter.writeStringEntry(String.join(System.lineSeparator(), README_CONTENT), README_FILE_NAME); + } + + private void writeSubmissionIndexFile(JPlagResult result) { + List comparisons = result.getComparisons(result.getOptions().maximumNumberOfComparisons()); + Set submissions = getSubmissions(comparisons); + SubmissionFileIndex fileIndex = new SubmissionFileIndex(new HashMap<>()); + + List>> submissionTokenCountList = submissions.stream().parallel().map(submission -> { + Map tokenCounts = new HashMap<>(); + for (Map.Entry entry : submission.getTokenCountPerFile().entrySet()) { + String key = FilePathUtil.getRelativeSubmissionPath(entry.getKey(), submission, submissionToIdFunction); + tokenCounts.put(key, new SubmissionFile(entry.getValue())); + } + return Map.of(submissionNameToIdMap.get(submission.getName()), tokenCounts); + }).toList(); + submissionTokenCountList.forEach(submission -> fileIndex.fileIndexes().putAll(submission)); + this.resultWriter.addJsonEntry(fileIndex, SUBMISSION_FILE_INDEX_FILE_NAME); + } + + private void writeOptionsFiles(JPlagOptions options) { + resultWriter.addJsonEntry(options, OPTIONS_FILE_NAME); } private Set getSubmissions(List comparisons) { @@ -197,16 +196,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..f207279dc 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,11 @@ * 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, + @JsonProperty("first_similarity") double firstSimilarity, @JsonProperty("second_similarity") double secondSimilarity) { } diff --git a/core/src/main/java/de/jplag/reporting/reportobject/model/Metric.java b/core/src/main/java/de/jplag/reporting/reportobject/model/Metric.java deleted file mode 100644 index d95b1f71a..000000000 --- a/core/src/main/java/de/jplag/reporting/reportobject/model/Metric.java +++ /dev/null @@ -1,9 +0,0 @@ -package de.jplag.reporting.reportobject.model; - -import java.util.List; - -import com.fasterxml.jackson.annotation.JsonProperty; - -public record Metric(@JsonProperty("name") String name, @JsonProperty("distribution") List distribution, - @JsonProperty("topComparisons") List topComparisons, @JsonProperty String description) { -} 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/SubmissionFile.java b/core/src/main/java/de/jplag/reporting/reportobject/model/SubmissionFile.java new file mode 100644 index 000000000..33754b2a4 --- /dev/null +++ b/core/src/main/java/de/jplag/reporting/reportobject/model/SubmissionFile.java @@ -0,0 +1,6 @@ +package de.jplag.reporting.reportobject.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public record SubmissionFile(@JsonProperty("token_count") int tokenCount) { +} 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..f33589044 --- /dev/null +++ b/core/src/main/java/de/jplag/reporting/reportobject/model/SubmissionFileIndex.java @@ -0,0 +1,8 @@ +package de.jplag.reporting.reportobject.model; + +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/reporting/reportobject/writer/DummyResultWriter.java b/core/src/main/java/de/jplag/reporting/reportobject/writer/DummyResultWriter.java new file mode 100644 index 000000000..1da95b72d --- /dev/null +++ b/core/src/main/java/de/jplag/reporting/reportobject/writer/DummyResultWriter.java @@ -0,0 +1,37 @@ +package de.jplag.reporting.reportobject.writer; + +import java.io.File; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Dummy writer, that does nothing + */ +public class DummyResultWriter implements JPlagResultWriter { + private static final Logger logger = LoggerFactory.getLogger(DummyResultWriter.class); + private static final String MESSAGE_JSON = "DummyWriter writes object {} to path {} as JSON."; + private static final String MESSAGE_FILE = "DummyWriter writes file {} to path {}."; + private static final String MESSAGE_STRING = "DummyWriter writes String ({}) to path {}."; + private static final String MESSAGE_CLOSE = "DummyWriter closed."; + + @Override + public void addJsonEntry(Object jsonContent, String path) { + logger.info(MESSAGE_JSON, jsonContent, path); + } + + @Override + public void addFileContentEntry(String path, File original) { + logger.info(MESSAGE_FILE, original.getAbsolutePath(), path); + } + + @Override + public void writeStringEntry(String entry, String path) { + logger.info(MESSAGE_STRING, entry, path); + } + + @Override + public void close() { + logger.info(MESSAGE_CLOSE); + } +} diff --git a/core/src/main/java/de/jplag/reporting/reportobject/writer/JPlagResultWriter.java b/core/src/main/java/de/jplag/reporting/reportobject/writer/JPlagResultWriter.java new file mode 100644 index 000000000..57fbed8c4 --- /dev/null +++ b/core/src/main/java/de/jplag/reporting/reportobject/writer/JPlagResultWriter.java @@ -0,0 +1,34 @@ +package de.jplag.reporting.reportobject.writer; + +import java.io.File; + +/** + * Writer for JPlag result data. The way paths are resolved depends on the implementation + */ +public interface JPlagResultWriter { + /** + * Writes data as json + * @param jsonContent The json content + * @param path The path to write to + */ + void addJsonEntry(Object jsonContent, String path); + + /** + * Writes data from a file + * @param path The path to write to + * @param original The original file + */ + void addFileContentEntry(String path, File original); + + /** + * Writes data from a string + * @param entry The string to write + * @param path The path to write to + */ + void writeStringEntry(String entry, String path); + + /** + * Closes the writer + */ + void close(); +} diff --git a/core/src/main/java/de/jplag/reporting/reportobject/writer/ZipWriter.java b/core/src/main/java/de/jplag/reporting/reportobject/writer/ZipWriter.java new file mode 100644 index 000000000..b7606c535 --- /dev/null +++ b/core/src/main/java/de/jplag/reporting/reportobject/writer/ZipWriter.java @@ -0,0 +1,80 @@ +package de.jplag.reporting.reportobject.writer; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Writes JPlag result data as a zip + */ +public class ZipWriter implements JPlagResultWriter { + private static final Logger logger = LoggerFactory.getLogger(ZipWriter.class); + private static final ObjectMapper objectMapper = new ObjectMapper(); + + private static final String WRITE_JSON_ERROR = "Failed to write JSON entry %s"; + private static final String COPY_FILE_ERROR = "Failed to copy file (%s) to entry (%s)"; + private static final String WRITE_STRING_ERROR = "Failed to write string entry %s"; + private static final String CLOSE_FILE_ERROR = "Failed to close zip file properly"; + + private final ZipOutputStream file; + + /** + * The zip file to write to + * @param zipFile The file + * @throws FileNotFoundException If the file cannot be opened for writing + */ + public ZipWriter(File zipFile) throws FileNotFoundException { + zipFile.getAbsoluteFile().getParentFile().mkdirs(); + this.file = new ZipOutputStream(new FileOutputStream(zipFile)); + } + + @Override + public void addJsonEntry(Object jsonContent, String path) { + try { + this.file.putNextEntry(new ZipEntry(path)); + this.file.write(objectMapper.writeValueAsBytes(jsonContent)); + this.file.closeEntry(); + } catch (IOException e) { + logger.error(String.format(WRITE_JSON_ERROR, path), e); + } + } + + @Override + public void addFileContentEntry(String path, File original) { + try (FileInputStream inputStream = new FileInputStream(original)) { + this.file.putNextEntry(new ZipEntry(path)); + inputStream.transferTo(this.file); + } catch (IOException e) { + logger.error(String.format(COPY_FILE_ERROR, original.getAbsolutePath(), path), e); + } + } + + @Override + public void writeStringEntry(String entry, String path) { + try { + this.file.putNextEntry(new ZipEntry(path)); + this.file.write(entry.getBytes(StandardCharsets.UTF_8)); + } catch (IOException e) { + logger.error(String.format(WRITE_STRING_ERROR, path), e); + } + } + + @Override + public void close() { + try { + this.file.close(); + } catch (IOException e) { + logger.error(CLOSE_FILE_ERROR, e); + } + } +} diff --git a/core/src/main/java/de/jplag/strategy/AbstractComparisonStrategy.java b/core/src/main/java/de/jplag/strategy/AbstractComparisonStrategy.java index 5ee516e13..29809df31 100644 --- a/core/src/main/java/de/jplag/strategy/AbstractComparisonStrategy.java +++ b/core/src/main/java/de/jplag/strategy/AbstractComparisonStrategy.java @@ -3,28 +3,32 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.stream.Stream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import de.jplag.GreedyStringTiling; import de.jplag.JPlagComparison; +import de.jplag.JPlagResult; import de.jplag.Submission; import de.jplag.SubmissionSet; +import de.jplag.logging.ProgressBar; +import de.jplag.logging.ProgressBarLogger; +import de.jplag.logging.ProgressBarType; import de.jplag.options.JPlagOptions; 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; - protected final JPlagOptions options; + private final JPlagOptions options; protected AbstractComparisonStrategy(JPlagOptions options, GreedyStringTiling greedyStringTiling) { this.greedyStringTiling = greedyStringTiling; this.options = options; - logger.info("Start comparing..."); } /** @@ -47,7 +51,7 @@ protected void compareSubmissionsToBaseCode(SubmissionSet submissionSet) { */ protected Optional compareSubmissions(Submission first, Submission second) { JPlagComparison comparison = greedyStringTiling.compare(first, second); - logger.info("Comparing {}-{}: {}", first.getName(), second.getName(), comparison.similarity()); + logger.trace("Comparing {}-{}: {}", first.getName(), second.getName(), comparison.similarity()); if (options.similarityMetric().isAboveThreshold(comparison, options.similarityThreshold())) { return Optional.of(comparison); @@ -58,7 +62,7 @@ protected Optional compareSubmissions(Submission first, Submiss /** * @return a list of all submission tuples to be processed. */ - protected static List buildComparisonTuples(List submissions) { + private List buildComparisonTuples(List submissions) { List tuples = new ArrayList<>(); List validSubmissions = submissions.stream().filter(s -> s.getTokenList() != null).toList(); @@ -73,4 +77,44 @@ protected static List buildComparisonTuples(List su } return tuples; } + + @Override + public JPlagResult compareSubmissions(SubmissionSet submissionSet) { + long timeBeforeStartInMillis = System.currentTimeMillis(); + + handleBaseCode(submissionSet); + + List tuples = buildComparisonTuples(submissionSet.getSubmissions()); + ProgressBar progressBar = ProgressBarLogger.createProgressBar(ProgressBarType.COMPARING, tuples.size()); + List comparisons = prepareStream(tuples).flatMap(tuple -> { + Optional result = compareTuple(tuple); + progressBar.step(); + return result.stream(); + }).toList(); + progressBar.dispose(); + + long durationInMillis = System.currentTimeMillis() - timeBeforeStartInMillis; + + return new JPlagResult(comparisons, submissionSet, durationInMillis, options); + } + + /** + * Handle the parsing of the base code. + * @param submissionSet The submission set to parse + */ + protected abstract void handleBaseCode(SubmissionSet submissionSet); + + /** + * Prepare a stream for parsing the tuples. Here you can modify the tuples or the stream as necessary. + * @param tuples The tuples to stream + * @return The Stream of tuples + */ + protected abstract Stream prepareStream(List tuples); + + /** + * Compares a single tuple. Returns nothing, if the similarity is not high enough. + * @param tuple The Tuple to compare + * @return The comparison + */ + protected abstract Optional compareTuple(SubmissionTuple tuple); } diff --git a/core/src/main/java/de/jplag/strategy/ParallelComparisonStrategy.java b/core/src/main/java/de/jplag/strategy/ParallelComparisonStrategy.java index fd94b9293..43cc66ae6 100644 --- a/core/src/main/java/de/jplag/strategy/ParallelComparisonStrategy.java +++ b/core/src/main/java/de/jplag/strategy/ParallelComparisonStrategy.java @@ -2,10 +2,10 @@ import java.util.List; import java.util.Optional; +import java.util.stream.Stream; import de.jplag.GreedyStringTiling; import de.jplag.JPlagComparison; -import de.jplag.JPlagResult; import de.jplag.SubmissionSet; import de.jplag.options.JPlagOptions; @@ -19,19 +19,20 @@ public ParallelComparisonStrategy(JPlagOptions options, GreedyStringTiling greed } @Override - public JPlagResult compareSubmissions(SubmissionSet submissionSet) { - // Initialize: - long timeBeforeStartInMillis = System.currentTimeMillis(); + protected void handleBaseCode(SubmissionSet submissionSet) { boolean withBaseCode = submissionSet.hasBaseCode(); if (withBaseCode) { compareSubmissionsToBaseCode(submissionSet); } + } - List tuples = buildComparisonTuples(submissionSet.getSubmissions()); - List comparisons = tuples.stream().parallel().map(tuple -> compareSubmissions(tuple.left(), tuple.right())) - .flatMap(Optional::stream).toList(); + @Override + protected Stream prepareStream(List tuples) { + return tuples.stream().parallel(); + } - long durationInMillis = System.currentTimeMillis() - timeBeforeStartInMillis; - return new JPlagResult(comparisons, submissionSet, durationInMillis, options); + @Override + protected Optional compareTuple(SubmissionTuple tuple) { + return compareSubmissions(tuple.left(), tuple.right()); } } diff --git a/core/src/main/resources/de/jplag/messages.properties b/core/src/main/resources/de/jplag/messages.properties deleted file mode 100644 index bd4b78a25..000000000 --- a/core/src/main/resources/de/jplag/messages.properties +++ /dev/null @@ -1,29 +0,0 @@ -CommandLineArgument.BaseCode=Path of the directory containing the base code (common framework used in all submissions) -CommandLineArgument.Debug=Debug parser. Non-parsable files will be stored -CommandLineArgument.Suffixes=comma-separated list of all filename suffixes that are included -CommandLineArgument.ExcludeFile=All files named in this file will be ignored in the comparison (line-separated list) -CommandLineArgument.Language=Select the language to parse the submissions -CommandLineArgument.MinTokenMatch=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 -CommandLineArgument.ResultFolder=Name of the directory in which the comparison results will be stored -CommandLineArgument.RootDirectory=Root directories with submissions to check for plagiarism -CommandLineArgument.NewDirectory=Root directories with submissions to check for plagiarism (same as the root directory) -CommandLineArgument.OldDirectory=Root directories with prior submissions to compare against -CommandLineArgument.ShownComparisons=The maximum number of comparisons that will be shown in the generated report, if set to -1 all comparisons will be shown -CommandLineArgument.SimilarityThreshold=Comparison similarity threshold [0.0-1.0]: All comparisons above this threshold will be saved -CommandLineArgument.Subdirectory=Look in directories /*/ for programs -CommandLineArgument.ClusterDisable=Skips the clustering -CommandLineArgument.ClusterAlgorithm=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. -CommandLineArgument.ClusterMetric=The metric used for clustering. AVG is intersection over union, MAX can expose some attempts of obfuscation. -CommandLineArgument.ClusterSpectralBandwidth=Bandwidth of the matern kernel in the Gaussian Process used during the search for a good number of clusters for spectral clustering. 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. -CommandLineArgument.ClusterSpectralNoise=The result of each run in the search for good clusterings are random. The noise level models the variance in the "worth" of these results. It also acts as a regularization constant. -CommandLineArgument.ClusterSpectralMinRuns=Minimum number of k-Means executions during spectral clustering. With these initial clustering sizes are explored. -CommandLineArgument.ClusterSpectralMaxRuns=Maximum number of k-Means executions during spectral clustering. Any execution after the initial runs tries to balance between exploration of unknown clustering sizes and exploitation of clustering sizes known as good. -CommandLineArgument.ClusterSpectralKmeansIterations=Maximum number of iterations during each execution of the k-Means algorithm. -CommandLineArgument.ClusterAgglomerativeThreshold=Only clusters with an inter-cluster-similarity greater than this threshold are merged during agglomerative clustering. -CommandLineArgument.ClusterAgglomerativeInterClusterSimilarity=How to measure the similarity of two clusters during agglomerative clustering. Minimum, maximum or average similarity between the submissions in each cluster. -CommandLineArgument.ClusterPreprocessingNone=Do not use any preprocessing before clustering. Not recommended for spectral clustering. -CommandLineArgument.ClusterPreprocessingCdf=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 supressing similarities that are low compared to other similarities. -CommandLineArgument.ClusterPreprocessingPercentile=Any similarity smaller than the given percentile will be suppressed during clustering. -CommandLineArgument.ClusterPreprocessingThreshold=Any similarity smaller than the given threshold value will be suppressed during clustering. -SimilarityMetric.Avg.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. -SimilarityMetric.Max.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. 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..6f14ebf06 100644 --- a/core/src/test/java/de/jplag/NewJavaFeaturesTest.java +++ b/core/src/test/java/de/jplag/NewJavaFeaturesTest.java @@ -1,36 +1,49 @@ 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; import de.jplag.exceptions.ExitException; +import de.jplag.java.JavaLanguage; 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 int EXPECTED_MATCHES = 8; // might change if you add files to the submissions + private static final int NUMBER_OF_TEST_FILES = 8; + private static final double EXPECTED_SIMILARITY = 0.971; // might change if you add files to the submissions 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(String.valueOf(JavaLanguage.JAVA_VERSION)); + assumeTrue(isCorrectJavaVersion || isCiRun, VERSION_MISMATCH_MESSAGE.formatted(actualJavaVersion, JavaLanguage.JAVA_VERSION)); + JPlagResult result = runJPlagWithExclusionFile(ROOT_DIRECTORY, EXCLUSION_FILE_NAME); // Ensure test input did not change: assertEquals(2, result.getNumberOfSubmissions(), String.format(CHANGE_MESSAGE, "Submissions")); for (Submission submission : result.getSubmissions().getSubmissions()) { - assertEquals(6, submission.getFiles().size(), String.format(CHANGE_MESSAGE, "Files")); + assertEquals(NUMBER_OF_TEST_FILES, submission.getFiles().size(), String.format(CHANGE_MESSAGE, "Files")); } assertEquals(1, result.getAllComparisons().size(), String.format(CHANGE_MESSAGE, "Comparisons")); // 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..c6a9db9ed --- /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 final Map> tokenStringMap; + private final 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/RootFolderTest.java b/core/src/test/java/de/jplag/RootFolderTest.java index b2408c87f..c5acd3cb1 100644 --- a/core/src/test/java/de/jplag/RootFolderTest.java +++ b/core/src/test/java/de/jplag/RootFolderTest.java @@ -1,6 +1,7 @@ package de.jplag; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.File; import java.util.List; @@ -9,6 +10,7 @@ import org.junit.jupiter.api.Test; import de.jplag.exceptions.ExitException; +import de.jplag.exceptions.RootDirectoryException; /** * Test class for the multi-root feature and the old-new feature. @@ -69,10 +71,7 @@ void testDisjunctNewAndOldRootDirectories() throws ExitException { void testOverlappingNewAndOldDirectoriesOverlap() throws ExitException { List newDirectories = List.of(getBasePath(ROOT_2)); List oldDirectories = List.of(getBasePath(ROOT_2)); - JPlagResult result = runJPlag(newDirectories, oldDirectories, it -> it); - assertEquals(ROOT_COUNT_2, result.getNumberOfSubmissions()); - int numberOfExpectedComparison = 1; - assertEquals(numberOfExpectedComparison, result.getAllComparisons().size()); + assertThrows(RootDirectoryException.class, () -> runJPlag(newDirectories, oldDirectories, it -> it)); } @Test 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/csv/CsvPrinterTest.java b/core/src/test/java/de/jplag/csv/CsvPrinterTest.java new file mode 100644 index 000000000..4a2673274 --- /dev/null +++ b/core/src/test/java/de/jplag/csv/CsvPrinterTest.java @@ -0,0 +1,35 @@ +package de.jplag.csv; + +import java.io.IOException; +import java.util.List; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class CsvPrinterTest { + private static final String EXPECTED_CSV_TEXT = "1,test1\r\n2,\"test2,\"\"x\"\"\"\r\n"; + private static final List TEST_ITEMS = List.of(new CsvTestItem(1, "test1"), new CsvTestItem(2, "test2,\"x\"")); + + @Test + void testPrintWithReflectiveMapper() throws IOException { + CsvDataMapper mapper = new ReflectiveCsvDataMapper<>(CsvTestItem.class); + CsvPrinter printer = new CsvPrinter<>(mapper); + + printer.addRows(TEST_ITEMS); + + Assertions.assertEquals(EXPECTED_CSV_TEXT, printer.printToString()); + } + + @Test + void testPrintWithHardcodedMapper() throws IOException { + CsvDataMapper mapper = new HardcodedCsvDataMapper<>(2, item -> new Object[] {item.number(), item.text()}); + CsvPrinter printer = new CsvPrinter<>(mapper); + + printer.addRows(TEST_ITEMS); + + Assertions.assertEquals(EXPECTED_CSV_TEXT, printer.printToString()); + } + + private record CsvTestItem(@CsvValue(1) int number, @CsvValue(2) String text) { + } +} 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..e2a606e16 --- /dev/null +++ b/core/src/test/java/de/jplag/merging/MergingTest.java @@ -0,0 +1,231 @@ +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.Comparator; +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 final JPlagOptions options; + private List matches; + private List comparisonsBefore; + private List comparisonsAfter; + private final ComparisonStrategy comparisonStrategy; + private final SubmissionSet submissionSet; + private static final int MINIMUM_NEIGHBOR_LENGTH = 1; + private static 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() { + JPlagResult result = comparisonStrategy.compareSubmissions(submissionSet); + comparisonsBefore = new ArrayList<>(result.getAllComparisons()); + + if (options.mergingOptions().enabled()) { + result = new MatchMerging(options).mergeMatchesOf(result); + } + comparisonsAfter = new ArrayList<>(result.getAllComparisons()); + + comparisonsBefore.sort(Comparator.comparing(Object::toString)); + comparisonsAfter.sort(Comparator.comparing(Object::toString)); + } + + @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 (JPlagComparison comparison : comparisons) { + matches = matchFunction.apply(comparison); + for (Match match : matches) { + assertTrue(match.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()); + sortedByFirst.sort(Comparator.comparingInt(Match::startOfFirst)); + for (Match match : matches) { + int begin = -1; + for (int k = 0; k < sortedByFirst.size(); k++) { + if (sortedByFirst.get(k).startOfFirst() == match.startOfFirst()) { + begin = k; + break; + } + } + if (begin == -1) { + correctMerges = false; + } else { + int foundToken = 0; + while (foundToken < match.length()) { + foundToken += sortedByFirst.get(begin).length(); + begin++; + if (foundToken > match.length()) { + correctMerges = false; + } + } + } + } + } + assertTrue(correctMerges); + } + + @Test + @DisplayName("Sanity check for match merging") + void testSanity() { + + List matchesBefore = new ArrayList<>(); + List matchesAfter = new ArrayList<>(); + + for (JPlagComparison comparison : comparisonsBefore) { + if (comparison.toString().equals("sanityA.java <-> sanityB.java")) { + matchesBefore = comparison.ignoredMatches(); + } + } + for (JPlagComparison comparison : comparisonsAfter) { + if (comparison.toString().equals("sanityA.java <-> sanityB.java")) { + matchesAfter = comparison.matches(); + } + } + + List expectedBefore = new ArrayList<>(); + expectedBefore.add(new Match(5, 3, 6)); + expectedBefore.add(new Match(11, 12, 6)); + expectedBefore.add(new Match(0, 0, 3)); + expectedBefore.add(new Match(3, 18, 2)); + expectedBefore.add(new Match(17, 20, 2)); + + List expectedAfter = new ArrayList<>(); + expectedAfter.add(new Match(5, 3, 12)); + + assertEquals(expectedBefore, matchesBefore); + assertEquals(expectedAfter, matchesAfter); + } +} \ No newline at end of file diff --git a/core/src/test/java/de/jplag/reporting/FilePathUtilTest.java b/core/src/test/java/de/jplag/reporting/FilePathUtilTest.java new file mode 100644 index 000000000..661d7cc0b --- /dev/null +++ b/core/src/test/java/de/jplag/reporting/FilePathUtilTest.java @@ -0,0 +1,26 @@ +package de.jplag.reporting; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +class FilePathUtilTest { + private static final String JOINED = "left/right"; + private static final String LEFT = "left"; + private static final String RIGHT = "right"; + + @Test + void testJoinPath() { + assertEquals(JOINED, FilePathUtil.joinZipPathSegments(LEFT, RIGHT)); + } + + @Test + void testJoinPathWithLeftSlashSuffix() { + assertEquals(JOINED, FilePathUtil.joinZipPathSegments(LEFT + "/", RIGHT)); + } + + @Test + void testJoinPathWithRightSlashSuffix() { + assertEquals(JOINED, FilePathUtil.joinZipPathSegments(LEFT, "/" + RIGHT)); + } +} \ No newline at end of file diff --git a/core/src/test/java/de/jplag/reporting/jsonfactory/DirectoryManagerTest.java b/core/src/test/java/de/jplag/reporting/jsonfactory/DirectoryManagerTest.java deleted file mode 100644 index f95b34932..000000000 --- a/core/src/test/java/de/jplag/reporting/jsonfactory/DirectoryManagerTest.java +++ /dev/null @@ -1,70 +0,0 @@ -package de.jplag.reporting.jsonfactory; - -import static org.junit.jupiter.api.Assertions.fail; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Path; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import de.jplag.TestBase; - -/** - * Test for the directory manager that persists the results for the report viewer. - */ -class DirectoryManagerTest extends TestBase { - private static final Path OUTPUT_PATH = Path.of(BASE_PATH, "output", "submissions"); - - private static final String SUBMISSION_1 = "A"; - private static final String FILE_PATH_1 = "TerrainType.java"; - private static final String ROOT_1 = "basecode"; - - private static final String SUBMISSION_2 = "Submission1.java"; - private static final String ROOT_2 = "FilesAsSubmissions"; - - private static final String SUBMISSION_3 = "A"; - private static final Path FILE_PATH_3 = Path.of("B", "A", "TerrainType.java"); - private static final String ROOT_3 = "basecode-sameNameOfSubdirectoryAndRootdirectory"; - - @Test - @DisplayName("test normal submission with file in folder") - void testCreateDirectoryBasecode() throws IOException { - testDirectoryManager(ROOT_1, SUBMISSION_1, FILE_PATH_1); - } - - @Test - @DisplayName("test single file as submission") - void testCreateDirectoryFileAsSubmission() throws IOException { - testDirectoryManager(ROOT_2, SUBMISSION_2, ""); - } - - @Test - @DisplayName("test same name of subdirectory and root directory") - void testCreateDirectorySharedName() throws IOException { - testDirectoryManager(ROOT_3, SUBMISSION_3, FILE_PATH_3.toString()); - } - - /** - * Test the directory manager for a given scenario. - * @param rootName is the name of the root folder. - * @param submissionName is the name of the submission. - * @param filePath is the path to the file relative to the submission. Empty for single file submissions. - */ - private static void testDirectoryManager(String rootName, String submissionName, String filePath) { - File submissionPath = Path.of(BASE_PATH, rootName, submissionName).toFile(); - File fullFilePath = new File(submissionPath, filePath); - File expectation = new File(OUTPUT_PATH.toFile(), Path.of(submissionName, filePath.isEmpty() ? submissionName : filePath).toString()); - try { - File directory = DirectoryManager.createDirectory(OUTPUT_PATH.toString(), submissionName, fullFilePath, submissionPath); - Assertions.assertNotNull(directory); - Assertions.assertEquals(expectation.getPath(), directory.getPath()); - } catch (IOException e) { - fail("Directory manager threw an exception:", e); - } finally { - deleteDirectory(expectation); - } - } -} diff --git a/core/src/test/java/de/jplag/reporting/reportobject/ReportObjectFactoryTest.java b/core/src/test/java/de/jplag/reporting/reportobject/ReportObjectFactoryTest.java index 19e4ee05c..36a7f610d 100644 --- a/core/src/test/java/de/jplag/reporting/reportobject/ReportObjectFactoryTest.java +++ b/core/src/test/java/de/jplag/reporting/reportobject/ReportObjectFactoryTest.java @@ -4,7 +4,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; -import java.nio.file.Path; +import java.io.IOException; +import java.io.RandomAccessFile; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -15,11 +16,8 @@ import de.jplag.reporting.reportobject.model.Version; class ReportObjectFactoryTest extends TestBase { - private static final String FILE_SUFFIX = ".zip"; private static final String BASECODE = "basecode"; private static final String BASECODE_BASE = "basecode-base"; - private static final String OUTPUT = "output"; - private static final String SUBMISSIONS = "submissions"; @Test void testVersionLoading() { @@ -28,15 +26,28 @@ void testVersionLoading() { } @Test - void testCreateAndSaveReportWithBasecode() throws ExitException { + void testCreateAndSaveReportWithBasecode() throws ExitException, IOException { JPlagResult result = runJPlag(BASECODE, it -> it.withBaseCodeSubmissionDirectory(new File(BASE_PATH, BASECODE_BASE))); - Path path = Path.of(BASE_PATH, OUTPUT, SUBMISSIONS); - ReportObjectFactory reportObjectFactory = new ReportObjectFactory(); - reportObjectFactory.createAndSaveReport(result, path.toString()); + File testZip = File.createTempFile("result", ".zip"); + + ReportObjectFactory reportObjectFactory = new ReportObjectFactory(testZip); + reportObjectFactory.createAndSaveReport(result); + assertNotNull(result); - File expectedFile = new File(path.toString() + FILE_SUFFIX); - assertTrue(expectedFile.exists()); - expectedFile.delete(); + assertTrue(isArchive(testZip)); + } + + /** + * Checks if the given file is a valid archive + * @param file The file to check + * @return True, if file is an archive + */ + private static boolean isArchive(File file) throws IOException { + int fileSignature = 0; + try (RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r")) { + fileSignature = randomAccessFile.readInt(); + } + return fileSignature == 0x504B0304 || fileSignature == 0x504B0506 || fileSignature == 0x504B0708; } } \ No newline at end of file diff --git a/core/src/test/java/de/jplag/reporting/reportobject/mapper/ComparisonReportWriterTest.java b/core/src/test/java/de/jplag/reporting/reportobject/mapper/ComparisonReportWriterTest.java index ffde264e9..72ebe4b16 100644 --- a/core/src/test/java/de/jplag/reporting/reportobject/mapper/ComparisonReportWriterTest.java +++ b/core/src/test/java/de/jplag/reporting/reportobject/mapper/ComparisonReportWriterTest.java @@ -10,18 +10,18 @@ import de.jplag.TestBase; import de.jplag.exceptions.ExitException; import de.jplag.reporting.jsonfactory.ComparisonReportWriter; -import de.jplag.reporting.jsonfactory.DummyWriter; -import de.jplag.reporting.jsonfactory.FileWriter; +import de.jplag.reporting.reportobject.writer.DummyResultWriter; +import de.jplag.reporting.reportobject.writer.JPlagResultWriter; public class ComparisonReportWriterTest extends TestBase { - private final FileWriter fileWriter = new DummyWriter(); + private final JPlagResultWriter fileWriter = new DummyResultWriter(); @Test public void firsLevelOfLookupMapComplete() throws ExitException { JPlagResult result = runJPlagWithDefaultOptions("PartialPlagiarism"); var mapper = new ComparisonReportWriter(Submission::getName, fileWriter); - Map> stringMapMap = mapper.writeComparisonReports(result, ""); + Map> stringMapMap = mapper.writeComparisonReports(result); firstLevelOfMapContains(stringMapMap, "A", "B", "C", "D", "E"); } @@ -31,7 +31,7 @@ public void secondLevelOfLookupMapComplete() throws ExitException { JPlagResult result = runJPlagWithDefaultOptions("PartialPlagiarism"); var mapper = new ComparisonReportWriter(Submission::getName, fileWriter); - Map> stringMapMap = mapper.writeComparisonReports(result, ""); + Map> stringMapMap = mapper.writeComparisonReports(result); secondLevelOfMapContains(stringMapMap, "A", "B", "C", "D", "E"); secondLevelOfMapContains(stringMapMap, "B", "A", "C", "D", "E"); 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..4127979ea 100644 --- a/core/src/test/java/de/jplag/special/ReadmeCodeExampleTest.java +++ b/core/src/test/java/de/jplag/special/ReadmeCodeExampleTest.java @@ -1,6 +1,7 @@ package de.jplag.special; import java.io.File; +import java.io.FileNotFoundException; import java.util.Set; import org.junit.jupiter.api.Disabled; @@ -10,6 +11,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,20 +27,21 @@ 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(); - reportObjectFactory.createAndSaveReport(result, "/path/to/output"); + ReportObjectFactory reportObjectFactory = new ReportObjectFactory(new File("/path/to/output")); + reportObjectFactory.createAndSaveReport(result); } catch (ExitException e) { // error handling here + } catch (FileNotFoundException e) { + // handle IO exception here } } } diff --git a/core/src/test/resources/de/jplag/samples/NewJavaFeatures/A/Java21.java b/core/src/test/resources/de/jplag/samples/NewJavaFeatures/A/Java21.java new file mode 100644 index 000000000..7917a5005 --- /dev/null +++ b/core/src/test/resources/de/jplag/samples/NewJavaFeatures/A/Java21.java @@ -0,0 +1,31 @@ +public class Java21 { + private static final record Circle(int radius) { + } + + private static final record Rect(int width, int height) { + } + + private static final record Both(Circle circle, Rect rect) { + } + + private static final record Square(int length) { + } + + public void main() { + Shape s = new Circle(); + switch (s) { + case Cricle(int r) -> System.out.println(r); + case Shape s -> System.out.println(c); + case Both(Circle c, Rect(int w, int _)) -> System.out.println("something"); + case Square -> { + int l = ((Square) s).length; + System.out.println(STR."Square with length \{Math.abs(l)}"); + } + } + + + if (s instanceof Circle(int r)) { + + } + } +} \ No newline at end of file diff --git a/core/src/test/resources/de/jplag/samples/NewJavaFeatures/B/Java21.java b/core/src/test/resources/de/jplag/samples/NewJavaFeatures/B/Java21.java new file mode 100644 index 000000000..ac503afab --- /dev/null +++ b/core/src/test/resources/de/jplag/samples/NewJavaFeatures/B/Java21.java @@ -0,0 +1,31 @@ +public class Java21 { + private static final record Circle(int radius) { + } + + private static final record Rect(int width, int height) { + } + + private static final record Both(Circle circle, Rect rect) { + } + + private static final record Square(int length) { + } + + public void main() { + Shape s = new Circle(); + switch (s) { + case Cricle(int r) -> System.out.println(r); + case Shape s -> System.out.println(c); + case Both(Circle c, Rect(int _, int w)) -> System.out.println("something"); + case Square -> { + int l = ((Square) s).length; + System.out.println(STR."Square with length \{Math.abs(l)}"); + } + } + + + if (s instanceof Circle(int r)) { + + } + } +} \ No newline at end of file diff --git a/core/src/test/resources/de/jplag/samples/NewJavaFeatures/blacklist.txt b/core/src/test/resources/de/jplag/samples/NewJavaFeatures/blacklist.txt index 163769f63..e69de29bb 100644 --- a/core/src/test/resources/de/jplag/samples/NewJavaFeatures/blacklist.txt +++ b/core/src/test/resources/de/jplag/samples/NewJavaFeatures/blacklist.txt @@ -1 +0,0 @@ -Java17Preview.java \ No newline at end of file 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/sanityA.java b/core/src/test/resources/de/jplag/samples/merging/sanityA.java new file mode 100644 index 000000000..d4a042dc6 --- /dev/null +++ b/core/src/test/resources/de/jplag/samples/merging/sanityA.java @@ -0,0 +1,18 @@ +public class Minimal { + public static void main (String [] Argv) { + System.out.println("Test"); + System.out.println("Test"); + int a = 1; + a = 1; + int b = 1; + a = 1; + int c = 1; + a = 1; + int d = 1; + a = 1; + int e = 1; + a = 1; + int f = 1; + a = 1; + } +} \ No newline at end of file diff --git a/core/src/test/resources/de/jplag/samples/merging/sanityB.java b/core/src/test/resources/de/jplag/samples/merging/sanityB.java new file mode 100644 index 000000000..75c55752a --- /dev/null +++ b/core/src/test/resources/de/jplag/samples/merging/sanityB.java @@ -0,0 +1,21 @@ +public class Minimal { + public static void main (String [] Argv) { + int a = 1; + a = 1; + int b = 1; + a = 1; + int c = 1; + a = 1; + if(a==1){ + a = 2; + } + int d = 1; + a = 1; + int e = 1; + a = 1; + int f = 1; + a = 1; + System.out.println("Test"); + System.out.println("Test"); + } +} \ 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..71f01179a 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 @@ -51,6 +61,11 @@ csharp ${revision} + + de.jplag + c + ${revision} + de.jplag cpp @@ -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..ac231b6f4 --- /dev/null +++ b/docs/1.-How-to-Use-JPlag.md @@ -0,0 +1,244 @@ +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: +``` +Parameter descriptions: + [root-dirs[,root-dirs...]...] + Root-directory with submissions to check for plagiarism. + -bc, --bc, --base-code= + Path to the base code directory (common framework used in all submissions). + -l, --language= + Select the language of the submissions (default: java). See subcommands below. + -M, --mode=<{RUN, VIEW, RUN_AND_VIEW}> + The mode of JPlag: either only run analysis, only open the viewer, or do both (default: null) + -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: 500) + -new, --new=[,...] + Root-directories with submissions to check for plagiarism (same as root). + --normalize Activate the normalization of tokens. Supported for languages: Java, C++. + -old, --old=[,...] + Root-directories with prior submissions to compare against. + -r, --result-file= + Name of the file in which the comparison results will be stored (default: results). Missing .zip endings will be automatically added. + -t, --min-tokens= + Tunes the comparison sensitivity by adjusting the minimum token required to be counted as a matching section. A smaller value increases the sensitivity but might lead to more + false-positives. + +Advanced + --csv-export Export pairwise similarity values as a CSV file. + -d, --debug Store on-parsable files in error folder. + -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. + -P, --port= The port used for the internal report viewer (default: 1996). + -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=<{AGGLOMERATIVE, SPECTRAL}> + Specifies the clustering algorithm (default: spectral). + --cluster-metric=<{AVG, MIN, MAX, INTERSECTION}> + The similarity metric used for clustering (default: average similarity). + --cluster-skip Skips the cluster calculation. + +Subsequence Match Merging + --gap-size= + Maximal gap between neighboring matches to be merged (between 1 and minTokenMatch, default: 6). + --match-merging Enables merging of neighboring matches to counteract obfuscation attempts. + --neighbor-length= + Minimal length of neighboring matches to be merged (between 1 and minTokenMatch, default: 2). + +Subcommands (supported languages): + c + cpp + csharp + emf + emf-model + go + java + javascript + kotlin + llvmir + python3 + rlang + rust + scala + scheme + scxml + swift + text + typescript +``` + +*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(new File("/path/to/output")); + 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..c89bb8ee3 --- /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..a4dbf71f0 --- /dev/null +++ b/docs/4.-Adding-New-Languages.md @@ -0,0 +1,516 @@ +# 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(); +} +``` + +# Adding code highlighting to the report-viewer +To ensure your language gets properly registered and its code is correctly highlighted in the report-viewer: +1) Add your language to the `ParserLanguage` enum in 'src/model/Language.ts'. As the value for the entry use its frontend name. +2) Add your language to the switch-case in `src/utils/CodeHighlighter.ts` and return the correct [highlight.js name](https://github.com/highlightjs/highlight.js/blob/main/SUPPORTED_LANGUAGES.md). If your language is not supported by default, also register the language here. \ 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..406ce95cc --- /dev/null +++ b/docs/6.-Report-File-Generation.md @@ -0,0 +1,93 @@ +`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 +| options.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. + +- options.json + - This File contains all options given to JPlag either over the CLI or programmatically + +- 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..d6388bd54 --- /dev/null +++ b/docs/Home.md @@ -0,0 +1,38 @@ +

+ JPlag logo +

+ +## What is JPlag +JPlag finds pairwise similarities among a set of multiple programs. It can reliably detect software plagiarism and collusion in software development. All similarities are calculated locally, and no source code or plagiarism results are ever uploaded to the internet. JPlag supports a large number of programming and modeling languages. 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 (_obfusction_) between plagiarized files. + +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. + +**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. + +* ๐Ÿ“ˆ [JPlag Demo](https://jplag.github.io/Demo/) + +* ๐Ÿ›๏ธ [JPlag on Helmholtz RSD](https://helmholtz.software/software/jplag) + +* ๐Ÿคฉ [Give us Feedback in a **short (<5 min) survey**](https://docs.google.com/forms/d/e/1FAIpQLSckqUlXhIlJ-H2jtu2VmGf_mJt4hcnHXaDlwhpUL3XG1I8UYw/viewform?usp=sf_link) + +## 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 and report UI are different and provide fewer features. diff --git a/endtoend-testing/pom.xml b/endtoend-testing/pom.xml index 370211bfa..a4e438e84 100644 --- a/endtoend-testing/pom.xml +++ b/endtoend-testing/pom.xml @@ -18,7 +18,6 @@ de.jplag cli ${revision} - test de.jplag @@ -31,5 +30,11 @@ com.fasterxml.jackson.core jackson-databind + + com.tngtech.archunit + archunit-junit5 + 1.2.1 + test + diff --git a/endtoend-testing/src/main/java/de/jplag/endtoend/constants/TestDirectoryConstants.java b/endtoend-testing/src/main/java/de/jplag/endtoend/constants/TestDirectoryConstants.java index b0cd6a7ff..d1f21c0f9 100644 --- a/endtoend-testing/src/main/java/de/jplag/endtoend/constants/TestDirectoryConstants.java +++ b/endtoend-testing/src/main/java/de/jplag/endtoend/constants/TestDirectoryConstants.java @@ -12,18 +12,17 @@ private TestDirectoryConstants() { } /** - * Base path to the saved results + * Base path to the resources directory */ - public static final Path BASE_PATH_TO_RESULT_JSON = Path.of("src", "test", "resources", "results"); + public static final Path BASE_PATH_TO_RESOURCES = Path.of("src", "test", "resources"); /** - * Base path to the endToEnd testing resources + * Base path to the saved results */ - public static final Path BASE_PATH_TO_LANGUAGE_RESOURCES = Path.of("src", "test", "resources", "languageTestFiles"); + public static final Path BASE_PATH_TO_RESULT_JSON = BASE_PATH_TO_RESOURCES.resolve(Path.of("results")); /** - * Create the complete path to the submission files. Here the temporary system path is extended with the - * "SUBMISSION_DIRECTORY_NAME", which is predefined in this class. + * Base path to the data set descriptors */ - public static final Path TEMPORARY_SUBMISSION_DIRECTORY_NAME = Path.of("target", "testing-directory-submission"); + public static final Path BASE_PATH_TO_DATA_SET_DESCRIPTORS = BASE_PATH_TO_RESOURCES.resolve(Path.of("dataSets")); } diff --git a/endtoend-testing/src/main/java/de/jplag/endtoend/helper/FileHelper.java b/endtoend-testing/src/main/java/de/jplag/endtoend/helper/FileHelper.java index 06f3232e4..abc9991f3 100644 --- a/endtoend-testing/src/main/java/de/jplag/endtoend/helper/FileHelper.java +++ b/endtoend-testing/src/main/java/de/jplag/endtoend/helper/FileHelper.java @@ -1,12 +1,22 @@ package de.jplag.endtoend.helper; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Enumeration; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; /** * Helper class to perform all necessary operations or functions on files or folders. */ public class FileHelper { + private static final int ZIP_THRESHOLD_ENTRIES = 100000; + private static final int ZIP_THRESHOLD_SIZE = 1000000000; + private static final double ZIP_THRESHOLD_RATIO = 10; + private static final String ZIP_BOMB_ERROR_MESSAGE = "Refusing to unzip file (%s), because it seems to be a fork bomb"; private FileHelper() { // private constructor to prevent instantiation @@ -52,4 +62,63 @@ public static void createFileIfItDoesNotExist(File file) throws IOException { private static String createNewIOExceptionStringForFileOrFOlderCreation(File file) { return "The file/folder at the location [" + file.toString() + "] could not be created!"; } -} + + /** + * Unzips a given zip file into a given directory. + * @param zip The zip file to extract + * @param targetDirectory The target directory + * @throws IOException If io operations go wrong + */ + public static void unzip(File zip, File targetDirectory) throws IOException { + try (ZipFile zipFile = new ZipFile(zip)) { + Enumeration entries = zipFile.entries(); + File canonicalTarget = targetDirectory.getCanonicalFile(); + + long totalSizeArchive = 0; + long totalEntriesArchive = 0; + + while (entries.hasMoreElements()) { + totalEntriesArchive++; + + ZipEntry entry = entries.nextElement(); + File unzippedFile = new File(canonicalTarget, entry.getName()).getCanonicalFile(); + + if (unzippedFile.getAbsolutePath().startsWith(canonicalTarget.getAbsolutePath())) { + if (entry.isDirectory()) { + unzippedFile.mkdirs(); + } else { + unzippedFile.getParentFile().mkdirs(); + totalSizeArchive += extractZipElement(entry, zipFile, zip, unzippedFile); + } + } + + if ((totalSizeArchive > ZIP_THRESHOLD_SIZE) || (totalEntriesArchive > ZIP_THRESHOLD_ENTRIES)) { + throw new IllegalStateException(String.format(ZIP_BOMB_ERROR_MESSAGE, zip.getAbsolutePath())); + } + } + } + } + + private static long extractZipElement(ZipEntry entry, ZipFile zipFile, File zip, File target) throws IOException { + long totalSizeEntry = 0; + + try (InputStream inputStream = zipFile.getInputStream(entry)) { + try (OutputStream outputStream = new FileOutputStream(target)) { + byte[] buffer = new byte[2048]; + int count; + while ((count = inputStream.read(buffer)) > 0) { + outputStream.write(buffer, 0, count); + + totalSizeEntry += count; + + double compressionRate = (double) totalSizeEntry / entry.getCompressedSize(); + if (compressionRate > ZIP_THRESHOLD_RATIO) { + throw new IllegalStateException(String.format(ZIP_BOMB_ERROR_MESSAGE, zip.getAbsolutePath())); + } + } + } + } + + return totalSizeEntry; + } +} \ No newline at end of file diff --git a/endtoend-testing/src/main/java/de/jplag/endtoend/helper/LanguageDeserializer.java b/endtoend-testing/src/main/java/de/jplag/endtoend/helper/LanguageDeserializer.java new file mode 100644 index 000000000..07848b72e --- /dev/null +++ b/endtoend-testing/src/main/java/de/jplag/endtoend/helper/LanguageDeserializer.java @@ -0,0 +1,21 @@ +package de.jplag.endtoend.helper; + +import java.io.IOException; + +import de.jplag.Language; +import de.jplag.cli.LanguageLoader; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; + +/** + * Deserialized a language from a json file + */ +public class LanguageDeserializer extends JsonDeserializer { + @Override + public Language deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { + String name = jsonParser.getText(); + return LanguageLoader.getLanguage(name).orElseThrow(() -> new IllegalStateException(String.format("Language %s not found.", name))); + } +} diff --git a/endtoend-testing/src/main/java/de/jplag/endtoend/helper/TestSuiteHelper.java b/endtoend-testing/src/main/java/de/jplag/endtoend/helper/TestSuiteHelper.java index bc4c03050..200323ae2 100644 --- a/endtoend-testing/src/main/java/de/jplag/endtoend/helper/TestSuiteHelper.java +++ b/endtoend-testing/src/main/java/de/jplag/endtoend/helper/TestSuiteHelper.java @@ -1,13 +1,10 @@ package de.jplag.endtoend.helper; -import java.io.File; -import java.util.List; import java.util.stream.Collectors; +import java.util.stream.Stream; import de.jplag.JPlagComparison; -import de.jplag.Language; import de.jplag.Submission; -import de.jplag.endtoend.constants.TestDirectoryConstants; /** * Helper class to perform all necessary additional functions for the endToEnd tests. @@ -28,30 +25,8 @@ private TestSuiteHelper() { * @return unique identifier for test case recognition */ public static String getTestIdentifier(JPlagComparison jPlagComparison) { - return List.of(jPlagComparison.firstSubmission(), jPlagComparison.secondSubmission()).stream().map(Submission::getRoot) + return Stream.of(jPlagComparison.firstSubmission(), jPlagComparison.secondSubmission()).map(Submission::getRoot) .map(FileHelper::getFileNameWithoutFileExtension).sorted().collect(Collectors.joining("-")); } - - /** - * Returns the file pointing to the directory of the submissions for the given language and result json. The result - * json's name is expected to be equal to the test suite identifier. - * @param language is the language for the tests - * @param resultJSON is the json containing the expected values - * @return returns the directory of the submissions - */ - public static File getSubmissionDirectory(Language language, File resultJSON) { - return getSubmissionDirectory(language, FileHelper.getFileNameWithoutFileExtension(resultJSON)); - } - - /** - * Returns the file pointing to the directory of the submissions for the given language and test suite identifier as - * described in the Readme.md. - * @param language is the langauge for the tests - * @param testSuiteIdentifier is the test suite identifier of the tests - * @return returns the directory of the submissions - */ - public static File getSubmissionDirectory(Language language, String testSuiteIdentifier) { - return TestDirectoryConstants.BASE_PATH_TO_LANGUAGE_RESOURCES.resolve(language.getIdentifier()).resolve(testSuiteIdentifier).toFile(); - } } diff --git a/endtoend-testing/src/main/java/de/jplag/endtoend/helper/UnzipManager.java b/endtoend-testing/src/main/java/de/jplag/endtoend/helper/UnzipManager.java new file mode 100644 index 000000000..332819cb5 --- /dev/null +++ b/endtoend-testing/src/main/java/de/jplag/endtoend/helper/UnzipManager.java @@ -0,0 +1,60 @@ +package de.jplag.endtoend.helper; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.attribute.FileAttribute; +import java.nio.file.attribute.PosixFilePermission; +import java.nio.file.attribute.PosixFilePermissions; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang3.SystemUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import de.jplag.endtoend.model.DataSet; + +public class UnzipManager { + private final Map unzippedFiles; + private static UnzipManager instance; + private final Logger logger = LoggerFactory.getLogger(UnzipManager.class); + + private static synchronized UnzipManager getInstance() { + if (instance == null) { + instance = new UnzipManager(); + } + + return instance; + } + + public static File unzipOrCache(DataSet dataSet, File zip) throws IOException { + return getInstance().unzipOrCacheInternal(dataSet, zip); + } + + private UnzipManager() { + this.unzippedFiles = new HashMap<>(); + } + + private File unzipOrCacheInternal(DataSet dataSet, File zip) throws IOException { + if (!unzippedFiles.containsKey(dataSet)) { + File target; + + if (SystemUtils.IS_OS_UNIX) { + FileAttribute> attr = PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rwx------")); + target = Files.createTempDirectory(zip.getName(), attr).toFile(); + } else { + target = Files.createTempDirectory(zip.getName()).toFile(); + if (!(target.setReadable(true, true) && target.setWritable(true, true) && target.setExecutable(true, true))) { + logger.warn("Could not set permissions for temp directory ({}).", target.getAbsolutePath()); + } + } + + FileHelper.unzip(zip, target); + this.unzippedFiles.put(dataSet, target); + } + + return this.unzippedFiles.get(dataSet); + } +} diff --git a/endtoend-testing/src/main/java/de/jplag/endtoend/model/ComparisonIdentifier.java b/endtoend-testing/src/main/java/de/jplag/endtoend/model/ComparisonIdentifier.java new file mode 100644 index 000000000..13760f56f --- /dev/null +++ b/endtoend-testing/src/main/java/de/jplag/endtoend/model/ComparisonIdentifier.java @@ -0,0 +1,57 @@ +package de.jplag.endtoend.model; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.HashSet; +import java.util.Scanner; +import java.util.Set; + +/** + * Identifier for a comparison. The order of the names does not matter + * @param firstName The first name + * @param secondName The second name + */ +public record ComparisonIdentifier(String firstName, String secondName) { + private static final String INVALID_LINE_ERROR_MESSAGE = "Comparison identifier file (%s) has an invalid line: %s"; + + @Override + public boolean equals(Object o) { + if (!(o instanceof ComparisonIdentifier other)) { + return false; + } + + return (firstName.equals(other.firstName) && secondName.equals(other.secondName)) + || (secondName.equals(other.firstName) && firstName.equals(other.secondName)); + } + + @Override + public int hashCode() { + return firstName.hashCode() + secondName.hashCode(); + } + + /** + * Loads the identifiers stored in a csv (semicolon separated) file. + * @param file The file to load + * @return The comparisons in the file + */ + public static Set loadIdentifiersFromFile(File file, String delimiter) { + try (Scanner scanner = new Scanner(file)) { + Set identifiers = new HashSet<>(); + while (scanner.hasNextLine()) { + String[] parts = scanner.nextLine().split(delimiter); + if (parts.length != 2) { + throw new IllegalStateException(String.format(INVALID_LINE_ERROR_MESSAGE, file.getAbsolutePath(), String.join(delimiter, parts))); + } + identifiers.add(new ComparisonIdentifier(parts[0], parts[1])); + } + return identifiers; + } catch (FileNotFoundException e) { + throw new IllegalStateException(String.format("Comparisons could not be loaded for %s.", file.getName()), e); + } + } + + @Override + public String toString() { + return firstName + " - " + secondName; + } +} diff --git a/endtoend-testing/src/main/java/de/jplag/endtoend/model/DataSet.java b/endtoend-testing/src/main/java/de/jplag/endtoend/model/DataSet.java new file mode 100644 index 000000000..229018daa --- /dev/null +++ b/endtoend-testing/src/main/java/de/jplag/endtoend/model/DataSet.java @@ -0,0 +1,105 @@ +package de.jplag.endtoend.model; + +import java.io.File; +import java.io.IOException; +import java.util.HashSet; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; + +import de.jplag.Language; +import de.jplag.endtoend.constants.TestDirectoryConstants; +import de.jplag.endtoend.helper.LanguageDeserializer; +import de.jplag.endtoend.helper.UnzipManager; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +/** + * Represents a data set for the end-to-end test suite. + * @param name The name of the data set + * @param language The language + * @param format The format + * @param sourceLocation The source directory, may be null + * @param resultFile The result file name, may be null + * @param goldStandardFile The gold standard file, may be null + * @param options The options for the jplag runs, may be null + */ +public record DataSet(@JsonProperty(required = true) String name, + @JsonDeserialize(using = LanguageDeserializer.class) @JsonProperty(required = true) Language language, + @JsonProperty(required = true) DataSetFormat format, @JsonProperty String sourceLocation, @JsonProperty StorageFormat storageFormat, + @JsonProperty String resultFile, @JsonProperty String goldStandardFile, @JsonProperty String goldStandardDelimiter, + @JsonProperty Options options) { + + private static final String DEFAULT_GOLD_STANDARD_DELIMITER = ";"; + private static final String DEFAULT_SOURCE_DIRECTORY = "data/%s"; + private static final String DEFAULT_SOURCE_ZIP = "data/%s.zip"; + private static final String DEFAULT_RESULT_FILE_NAME = "%s.json"; + + /** + * Gets the source directories + * @return The source directories + */ + public Set getSourceDirectories() throws IOException { + return new HashSet<>(format.getSourceDirectories(this)); + } + + /** + * Helper function replacing null by the default value + * @return The source directory + */ + File actualSourceDirectory() throws IOException { + StorageFormat actualStorageFormat = storageFormat == null ? StorageFormat.DIRECTORY : storageFormat; + + if (actualStorageFormat == StorageFormat.DIRECTORY) { + String location = sourceLocation; + if (location == null) { + location = String.format(DEFAULT_SOURCE_DIRECTORY, this.name); + } + return new File(TestDirectoryConstants.BASE_PATH_TO_RESOURCES.toFile(), location); + } + if (actualStorageFormat == StorageFormat.ZIP) { + String location = sourceLocation; + if (location == null) { + location = String.format(DEFAULT_SOURCE_ZIP, this.name); + } + return UnzipManager.unzipOrCache(this, new File(TestDirectoryConstants.BASE_PATH_TO_RESOURCES.toFile(), location)); + } + + throw new IllegalStateException(); + } + + /** + * Helper function replacing null by the default value + * @return The result file + */ + public File getResultFile() { + if (resultFile == null) { + return new File(TestDirectoryConstants.BASE_PATH_TO_RESULT_JSON.toFile(), String.format(DEFAULT_RESULT_FILE_NAME, this.name)); + } + return new File(TestDirectoryConstants.BASE_PATH_TO_RESULT_JSON.toFile(), resultFile); + } + + /** + * @return The gold standard file as an optional. + */ + public Optional getGoldStandardFile() throws IOException { + File actualSourceDirectory = this.actualSourceDirectory(); + return Optional.ofNullable(this.goldStandardFile).map(name -> new File(actualSourceDirectory, name)); + } + + /** + * Helper function replacing null by the default value. + * @return The options + */ + public Options getOptions() { + return Objects.requireNonNullElseGet(this.options, Options::new); + } + + /** + * Returns the actual delimiter, replacing null by the default value + */ + public String getActualDelimiter() { + return Objects.requireNonNullElse(this.goldStandardDelimiter, DEFAULT_GOLD_STANDARD_DELIMITER); + } +} diff --git a/endtoend-testing/src/main/java/de/jplag/endtoend/model/DataSetFormat.java b/endtoend-testing/src/main/java/de/jplag/endtoend/model/DataSetFormat.java new file mode 100644 index 000000000..a3c312928 --- /dev/null +++ b/endtoend-testing/src/main/java/de/jplag/endtoend/model/DataSetFormat.java @@ -0,0 +1,56 @@ +package de.jplag.endtoend.model; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.Set; + +/** + * The available formats for data sets. + */ +@SuppressWarnings("unused") // The formats only referred to from the data set configuration +public enum DataSetFormat { + /** + * The progpedia format + */ + PROGPEDIA { + @Override + public Set getSourceDirectories(DataSet dataSet) throws IOException { + return Collections.singleton(new File(dataSet.actualSourceDirectory(), "ACCEPTED")); + } + + @Override + public File getBaseCodeDirectory(DataSet dataSet, String directoryName) throws IOException { + return new File(dataSet.actualSourceDirectory(), directoryName); + } + }, + /** + * Plain format where the submissions are flat within the source directory. + */ + PLAIN { + @Override + public Set getSourceDirectories(DataSet dataSet) throws IOException { + return Collections.singleton(dataSet.actualSourceDirectory()); + } + + @Override + public File getBaseCodeDirectory(DataSet dataSet, String directoryName) { + throw new IllegalStateException("Plain formatted data sets cannot include base code."); + } + }; + + /** + * Resolved the source directories for jplag + * @param dataSet The data set + * @return The source directories + */ + public abstract Set getSourceDirectories(DataSet dataSet) throws IOException; + + /** + * Resolves the base code directory + * @param dataSet The data set + * @param directoryName The name of the base code directory + * @return The base code directory + */ + public abstract File getBaseCodeDirectory(DataSet dataSet, String directoryName) throws IOException; +} diff --git a/endtoend-testing/src/main/java/de/jplag/endtoend/model/DataSetRunConfiguration.java b/endtoend-testing/src/main/java/de/jplag/endtoend/model/DataSetRunConfiguration.java new file mode 100644 index 000000000..2e0f59013 --- /dev/null +++ b/endtoend-testing/src/main/java/de/jplag/endtoend/model/DataSetRunConfiguration.java @@ -0,0 +1,40 @@ +package de.jplag.endtoend.model; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import de.jplag.options.JPlagOptions; + +/** + * A run configuration for the end-to-end tests + * @param jPlagOptions The jplag options to use + * @param identifier The identifier for the configuration + */ +public record DataSetRunConfiguration(JPlagOptions jPlagOptions, String identifier) { + private static final String IDENTIFIER_FORMAT = "MTM: %s"; + + /** + * Builds all configurations for a data set + * @param dataSet The data set + * @return The configurations + */ + public static List generateRunConfigurations(DataSet dataSet) throws IOException { + Options configuredOptions = dataSet.getOptions(); + List result = new ArrayList<>(); + + for (int minimumTokenMatch : configuredOptions.getMinimumTokenMatches()) { + JPlagOptions options = new JPlagOptions(dataSet.language(), dataSet.getSourceDirectories(), Set.of()); + options = options.withMinimumTokenMatch(minimumTokenMatch); + if (configuredOptions.baseCodeDirectory() != null) { + File baseCode = dataSet.format().getBaseCodeDirectory(dataSet, configuredOptions.baseCodeDirectory()); + options = options.withBaseCodeSubmissionDirectory(baseCode); + } + result.add(new DataSetRunConfiguration(options, String.format(IDENTIFIER_FORMAT, minimumTokenMatch))); + } + + return result; + } +} diff --git a/endtoend-testing/src/main/java/de/jplag/endtoend/model/ExpectedResult.java b/endtoend-testing/src/main/java/de/jplag/endtoend/model/ExpectedResult.java index 8d1d95aac..ff2408adb 100644 --- a/endtoend-testing/src/main/java/de/jplag/endtoend/model/ExpectedResult.java +++ b/endtoend-testing/src/main/java/de/jplag/endtoend/model/ExpectedResult.java @@ -1,13 +1,14 @@ package de.jplag.endtoend.model; +import de.jplag.JPlagComparison; import de.jplag.options.SimilarityMetric; import com.fasterxml.jackson.annotation.JsonProperty; /** * contains the current comparative values for the endToEnd tests. The comparative values were determined by discussion - * which can be found at https://github.com/jplag/JPlag/issues/548 Here this object is used for serialization and - * deserialization of the information from json to object or object to json. + * which can be found at GitHub.Here this object is used for + * serialization and deserialization of the information from json to object or object to json. */ public record ExpectedResult(@JsonProperty("minimal_similarity") double resultSimilarityMinimum, @JsonProperty("maximum_similarity") double resultSimilarityMaximum, @JsonProperty("matched_token_number") int resultMatchedTokenNumber) { @@ -23,8 +24,15 @@ public double getSimilarityForMetric(SimilarityMetric metric) { case MIN -> resultSimilarityMinimum(); case MAX -> resultSimilarityMaximum(); case INTERSECTION -> resultMatchedTokenNumber(); - default -> throw new IllegalArgumentException("Metric not supported!"); }; } + /** + * Creates an expected result from a comparison + * @param comparison The comparison + * @return The expected result + */ + public static ExpectedResult fromComparison(JPlagComparison comparison) { + return new ExpectedResult(comparison.minimalSimilarity(), comparison.maximalSimilarity(), comparison.getNumberOfMatchedTokens()); + } } diff --git a/endtoend-testing/src/main/java/de/jplag/endtoend/model/GoldStandard.java b/endtoend-testing/src/main/java/de/jplag/endtoend/model/GoldStandard.java new file mode 100644 index 000000000..60afa0d0f --- /dev/null +++ b/endtoend-testing/src/main/java/de/jplag/endtoend/model/GoldStandard.java @@ -0,0 +1,33 @@ +package de.jplag.endtoend.model; + +import java.util.Collection; +import java.util.DoubleSummaryStatistics; +import java.util.Set; + +import de.jplag.JPlagComparison; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * The data for the gold standard. + * @param matchAverage The average similarity of all submission in the gold standard + * @param nonMatchAverage The average similarity of all submission outside the gold standard + */ +public record GoldStandard(@JsonProperty double matchAverage, @JsonProperty double nonMatchAverage) { + public static GoldStandard buildFromComparisons(Collection comparisonList, Set comparisonIdentifiers) { + DoubleSummaryStatistics match = new DoubleSummaryStatistics(); + DoubleSummaryStatistics nonMatch = new DoubleSummaryStatistics(); + + for (JPlagComparison comparison : comparisonList) { + ComparisonIdentifier comparisonIdentifier = new ComparisonIdentifier(comparison.firstSubmission().getName(), + comparison.secondSubmission().getName()); + if (comparisonIdentifiers.contains(comparisonIdentifier)) { + match.accept(comparison.similarity()); + } else { + nonMatch.accept(comparison.similarity()); + } + } + + return new GoldStandard(match.getAverage(), nonMatch.getAverage()); + } +} diff --git a/endtoend-testing/src/main/java/de/jplag/endtoend/model/Options.java b/endtoend-testing/src/main/java/de/jplag/endtoend/model/Options.java index a6fcbf10c..c84041cf5 100644 --- a/endtoend-testing/src/main/java/de/jplag/endtoend/model/Options.java +++ b/endtoend-testing/src/main/java/de/jplag/endtoend/model/Options.java @@ -1,10 +1,65 @@ package de.jplag.endtoend.model; +import java.util.Arrays; +import java.util.Objects; + import com.fasterxml.jackson.annotation.JsonProperty; /** - * The object contains required options for the endToEndt tests which are important for the test suite. The options were - * determined by discussion which can be found at https://github.com/jplag/JPlag/issues/590. + * The object contains required options for the endToEnd tests which are important for the test suite. */ -public record Options(@JsonProperty("minimum_token_match") Integer minimumTokenMatch) { +public record Options(@JsonProperty Integer[] minimumTokenMatches, @JsonProperty String baseCodeDirectory) { + + private static final int[] defaultTokenMatches = new int[] {3, 9}; + + /** + * Initializes a new options object with minimumTokenMatch and baseCodeDirectory both being null + */ + public Options() { + this(null, null); + } + + /** + * Builds the list of all token matches that should be checked. That means all values from minimumTokenMatches and the + * default values (3 and 9) + * @return The values + */ + public int[] getMinimumTokenMatches() { + Integer[] configuredValues = minimumTokenMatches; + if (configuredValues == null) { + configuredValues = new Integer[0]; + } + + int[] values = new int[configuredValues.length + defaultTokenMatches.length]; + System.arraycopy(defaultTokenMatches, 0, values, 0, defaultTokenMatches.length); + for (int i = 0; i < configuredValues.length; i++) { + values[defaultTokenMatches.length + i] = configuredValues[i]; + } + + return values; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Options options = (Options) o; + return Arrays.equals(minimumTokenMatches, options.minimumTokenMatches) && Objects.equals(baseCodeDirectory, options.baseCodeDirectory); + } + + @Override + public int hashCode() { + int result = Objects.hash(baseCodeDirectory); + result = 31 * result + Arrays.hashCode(minimumTokenMatches); + return result; + } + + @Override + public String toString() { + return "Options{" + "minimumTokenMatches=" + Arrays.toString(minimumTokenMatches) + ", baseCodeDirectory='" + baseCodeDirectory + '\'' + '}'; + } } diff --git a/endtoend-testing/src/main/java/de/jplag/endtoend/model/ResultDescription.java b/endtoend-testing/src/main/java/de/jplag/endtoend/model/ResultDescription.java index e5935f9f4..c46cc6f6e 100644 --- a/endtoend-testing/src/main/java/de/jplag/endtoend/model/ResultDescription.java +++ b/endtoend-testing/src/main/java/de/jplag/endtoend/model/ResultDescription.java @@ -2,14 +2,13 @@ import java.util.Map; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; /** * Object that maps the results of the end top end tests using the identifierToResultMap. this creates a map of test - * data and its results for each possible option specified. this is important both for serializing the data into json - * format and for deserialization. + * stream and its results for each possible option specified. this is important both for serializing the stream into + * json format and for deserialization. */ -public record ResultDescription(@JsonIgnore String languageIdentifier, @JsonProperty("options") Options options, - @JsonProperty("tests") Map identifierToResultMap) { +public record ResultDescription(@JsonProperty String identifier, @JsonProperty("tests") Map identifierToResultMap, + @JsonProperty GoldStandard goldStandard) { } \ No newline at end of file diff --git a/endtoend-testing/src/main/java/de/jplag/endtoend/model/StorageFormat.java b/endtoend-testing/src/main/java/de/jplag/endtoend/model/StorageFormat.java new file mode 100644 index 000000000..ad60f2c32 --- /dev/null +++ b/endtoend-testing/src/main/java/de/jplag/endtoend/model/StorageFormat.java @@ -0,0 +1,6 @@ +package de.jplag.endtoend.model; + +public enum StorageFormat { + DIRECTORY, + ZIP +} 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..7d66b3274 100644 --- a/endtoend-testing/src/test/java/de/jplag/endtoend/EndToEndGeneratorTest.java +++ b/endtoend-testing/src/test/java/de/jplag/endtoend/EndToEndGeneratorTest.java @@ -5,7 +5,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.stream.Collectors; import org.junit.jupiter.api.Disabled; @@ -16,13 +15,14 @@ import de.jplag.JPlag; import de.jplag.JPlagComparison; import de.jplag.JPlagResult; -import de.jplag.Language; -import de.jplag.cli.LanguageLoader; import de.jplag.endtoend.constants.TestDirectoryConstants; import de.jplag.endtoend.helper.FileHelper; import de.jplag.endtoend.helper.TestSuiteHelper; +import de.jplag.endtoend.model.ComparisonIdentifier; +import de.jplag.endtoend.model.DataSet; +import de.jplag.endtoend.model.DataSetRunConfiguration; import de.jplag.endtoend.model.ExpectedResult; -import de.jplag.endtoend.model.Options; +import de.jplag.endtoend.model.GoldStandard; import de.jplag.endtoend.model.ResultDescription; import de.jplag.exceptions.ExitException; import de.jplag.options.JPlagOptions; @@ -32,54 +32,54 @@ /** * Test class for automatically generating the json file describing the expected results. To generate a result json, - * adapt the three constants to your requirements and enable the test case. + * adapt the DATA_SET constant. */ class EndToEndGeneratorTest { - private static final String LANGUAGE_IDENTIFIER = "java"; - private static final String TEST_SUITE_IDENTIFIER = "sortAlgo"; - private static final List OPTIONS = List.of(new Options(3), new Options(9)); + private static final String DATA_SET = "progpedia"; private static final Logger logger = LoggerFactory.getLogger(EndToEndGeneratorTest.class); @Disabled("only enable to generate result json file") @Test void generateResultJson() throws ExitException, IOException { - Language language = LanguageLoader.getLanguage(LANGUAGE_IDENTIFIER).orElseThrow(); - File submissionDirectory = TestSuiteHelper.getSubmissionDirectory(language, TEST_SUITE_IDENTIFIER); + DataSet dataSet = new ObjectMapper() + .readValue(new File(TestDirectoryConstants.BASE_PATH_TO_DATA_SET_DESCRIPTORS.toFile(), DATA_SET + ".json"), DataSet.class); List resultDescriptions = new ArrayList<>(); - for (var option : OPTIONS) { - JPlagOptions jplagOptions = new JPlagOptions(language, Set.of(submissionDirectory), Set.of()) - .withMinimumTokenMatch(option.minimumTokenMatch()); - JPlagResult jplagResult = new JPlag(jplagOptions).run(); - List jPlagComparisons = jplagResult.getAllComparisons(); - Map expectedResults = jPlagComparisons.stream() - .collect(Collectors.toMap(TestSuiteHelper::getTestIdentifier, comparison -> new ExpectedResult(comparison.minimalSimilarity(), - comparison.maximalSimilarity(), comparison.getNumberOfMatchedTokens()))); - resultDescriptions.add(new ResultDescription(language.getIdentifier(), option, expectedResults)); + + for (DataSetRunConfiguration runConfiguration : DataSetRunConfiguration.generateRunConfigurations(dataSet)) { + JPlagOptions options = runConfiguration.jPlagOptions(); + JPlagResult result = JPlag.run(options); + List comparisons = result.getAllComparisons(); + Map expectedResults = comparisons.stream() + .collect(Collectors.toMap(TestSuiteHelper::getTestIdentifier, ExpectedResult::fromComparison)); + + GoldStandard goldStandard = null; + if (dataSet.getGoldStandardFile().isPresent()) { + goldStandard = GoldStandard.buildFromComparisons(comparisons, + ComparisonIdentifier.loadIdentifiersFromFile(dataSet.getGoldStandardFile().get(), dataSet.getActualDelimiter())); + } + + resultDescriptions.add(new ResultDescription(runConfiguration.identifier(), expectedResults, goldStandard)); } - File outputFile = writeJsonModelsToJsonFile(resultDescriptions, TEST_SUITE_IDENTIFIER, LANGUAGE_IDENTIFIER); + + File outputFile = writeJsonModelsToJsonFile(resultDescriptions, dataSet); logger.info("result JSON written to file '{}'", outputFile); } /** * Saves the passed object as a json file to the file identified by the test suite and language. Returns that file. * @param resultDescriptions list of elements to be saved - * @param testSuiteIdentifier identifier of the test suite - * @param languageIdentifier identifier of the language - * @throws IOException Signals that an I/O exception of some sort has occurred. Thisclass is the general class of + * @param dataSet The data set the elements are for + * @throws IOException Signals that an I/O exception, of some sort, has occurred. Thisclass is the general class of * exceptions produced by failed orinterrupted I/O operations. */ - private static File writeJsonModelsToJsonFile(List resultDescriptions, String testSuiteIdentifier, String languageIdentifier) - throws IOException { + private static File writeJsonModelsToJsonFile(List resultDescriptions, DataSet dataSet) throws IOException { ObjectWriter writer = new ObjectMapper().writer().withDefaultPrettyPrinter(); - File outputFile = TestDirectoryConstants.TEMPORARY_SUBMISSION_DIRECTORY_NAME.resolve(languageIdentifier) - .resolve(testSuiteIdentifier + ".json").toFile(); + File outputFile = dataSet.getResultFile(); FileHelper.createDirectoryIfItDoesNotExist(outputFile.getParentFile()); FileHelper.createFileIfItDoesNotExist(outputFile); - // convert book object to JSON file - writer.writeValue(outputFile, resultDescriptions.toArray()); return outputFile; 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..30bb375b6 100644 --- a/endtoend-testing/src/test/java/de/jplag/endtoend/EndToEndSuiteTest.java +++ b/endtoend-testing/src/test/java/de/jplag/endtoend/EndToEndSuiteTest.java @@ -14,12 +14,17 @@ import java.util.Arrays; import java.util.Collection; import java.util.DoubleSummaryStatistics; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; +import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.DynamicContainer; +import org.junit.jupiter.api.DynamicNode; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; @@ -27,12 +32,16 @@ import de.jplag.JPlagComparison; import de.jplag.JPlagResult; import de.jplag.Language; -import de.jplag.cli.LanguageLoader; +import de.jplag.Submission; import de.jplag.endtoend.constants.TestDirectoryConstants; import de.jplag.endtoend.helper.DeltaSummaryStatistics; import de.jplag.endtoend.helper.FileHelper; import de.jplag.endtoend.helper.TestSuiteHelper; +import de.jplag.endtoend.model.ComparisonIdentifier; +import de.jplag.endtoend.model.DataSet; +import de.jplag.endtoend.model.DataSetRunConfiguration; import de.jplag.endtoend.model.ExpectedResult; +import de.jplag.endtoend.model.GoldStandard; import de.jplag.endtoend.model.ResultDescription; import de.jplag.exceptions.ExitException; import de.jplag.options.JPlagOptions; @@ -46,66 +55,106 @@ * previous ones stored in the resource folder. */ class EndToEndSuiteTest { - private static final double EPSILON = 1E-8; + private static final double EPSILON = 1E-6; /** * Creates the test cases over all language options for which data is available and the current test options. * @return dynamic test cases across all test data and languages - * @throws IOException is thrown for all problems that may occur while parsing the json file. + * @throws ExitException If JPlag throws an error */ @TestFactory - Collection endToEndTestFactory() throws ExitException { - File resultDirectory = TestDirectoryConstants.BASE_PATH_TO_RESULT_JSON.toFile(); - List languageDirectories = Arrays.asList(resultDirectory.listFiles(File::isDirectory)); + Collection endToEndTestFactory() throws ExitException, IOException { + File descriptorDirectory = TestDirectoryConstants.BASE_PATH_TO_DATA_SET_DESCRIPTORS.toFile(); + List testDescriptorFiles = Arrays.asList(Objects.requireNonNull(descriptorDirectory.listFiles())); List allTests = new ArrayList<>(); - for (File languageDirectory : languageDirectories) { - allTests.add(generateTestForLanguage(languageDirectory)); + + Map> dataSetsByLanguage = testDescriptorFiles.stream().map(testDescriptorFile -> { + try { + return new ObjectMapper().readValue(testDescriptorFile, DataSet.class); + } catch (IOException e) { + throw new IllegalStateException("The test descriptor " + testDescriptorFile.getName() + " is invalid."); + } + }).collect(Collectors.groupingBy(DataSet::language)); + + for (Language language : dataSetsByLanguage.keySet()) { + allTests.add(generateTestForLanguage(language, dataSetsByLanguage.get(language))); } + return allTests; } - private DynamicContainer generateTestForLanguage(File languageDirectory) throws ExitException { - Language language = LanguageLoader.getLanguage(languageDirectory.getName()).orElseThrow(); - File[] resultJsons = languageDirectory.listFiles(file -> !file.isDirectory() && file.getName().endsWith(".json")); + /** + * Generates the tests for the given language + * @param language The language + * @param dataSets The data sets for this language + * @return The dynamic container containing the tests + * @throws ExitException If JPlag throws an error + */ + private DynamicContainer generateTestForLanguage(Language language, List dataSets) throws ExitException, IOException { List languageTests = new LinkedList<>(); - for (File resultJson : resultJsons) { // for each data set - languageTests.add(generateTestsForDataSet(language, resultJson)); + for (DataSet dataSet : dataSets) { + languageTests.add(generateTestsForDataSet(dataSet)); } return DynamicContainer.dynamicContainer(language.getIdentifier(), languageTests); } - private DynamicContainer generateTestsForDataSet(Language language, File resultJson) throws ExitException { + /** + * Generates tests for a data set + * @param dataSet The data set + * @return The dynamic container containing the tests + * @throws ExitException If JPlag throws an error + */ + private DynamicContainer generateTestsForDataSet(DataSet dataSet) throws ExitException, IOException { List testContainers = new LinkedList<>(); - ResultDescription[] results; + Map results = new HashMap<>(); try { - results = new ObjectMapper().readValue(resultJson, ResultDescription[].class); + ResultDescription[] resultList = new ObjectMapper().readValue(dataSet.getResultFile(), ResultDescription[].class); + for (ResultDescription resultDescription : resultList) { + results.put(resultDescription.identifier(), resultDescription); + } } catch (IOException exception) { throw new IllegalStateException("Could not load expected values.", exception); } - for (var result : results) { // for each configuration - var testCases = generateTestsForResultDescription(resultJson, result, language); - testContainers.add(DynamicContainer.dynamicContainer("MTM: " + result.options().minimumTokenMatch(), testCases)); + + for (DataSetRunConfiguration runConfiguration : DataSetRunConfiguration.generateRunConfigurations(dataSet)) { + if (!results.containsKey(runConfiguration.identifier())) { + throw new IllegalStateException("Expected results don't match data set configuration"); + } + testContainers.add(generateTestsForResultDescription(results.get(runConfiguration.identifier()), dataSet, runConfiguration)); } - return DynamicContainer.dynamicContainer(FileHelper.getFileNameWithoutFileExtension(resultJson), testContainers); + + return DynamicContainer.dynamicContainer(FileHelper.getFileNameWithoutFileExtension(dataSet.getResultFile()), testContainers); } /** * Generates test cases for each test described in the provided result object. - * @param resultJson is the file of the result json * @param result is one test suite configuration of the deserialized {@code resultJson} - * @param language is the language to run JPlag with + * @param dataSet The data set, the test is for + * @param runConfiguration The run configuration for the test * @return a collection of test cases, each validating one {@link JPlagResult} against its {@link ExpectedResult} * counterpart + * @throws ExitException If JPlag throw an error */ - 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()) - .withMinimumTokenMatch(result.options().minimumTokenMatch()); - JPlagResult jplagResult = new JPlag(jplagOptions).run(); - var comparisons = jplagResult.getAllComparisons().stream().collect(Collectors.toMap(it -> TestSuiteHelper.getTestIdentifier(it), it -> it)); + private DynamicContainer generateTestsForResultDescription(ResultDescription result, DataSet dataSet, DataSetRunConfiguration runConfiguration) + throws ExitException, IOException { + JPlagOptions options = runConfiguration.jPlagOptions(); + JPlagResult jplagResult = JPlag.run(options); + var comparisons = jplagResult.getAllComparisons().stream().collect(Collectors.toMap(TestSuiteHelper::getTestIdentifier, it -> it)); assertEquals(result.identifierToResultMap().size(), comparisons.size(), "different number of results and expected results"); + DynamicContainer comparisonTests = generateTestResultsForComparisons(result, comparisons); + DynamicNode detectionTest = generateGoldStandardTest(dataSet, comparisons, result.goldStandard()); + + return DynamicContainer.dynamicContainer(runConfiguration.identifier(), List.of(comparisonTests, detectionTest)); + } + + /** + * Generates the test cases for the individual comparisons + * @param result The result description for the tests + * @param comparisons The comparisons + * @return The container with the tests + */ + private DynamicContainer generateTestResultsForComparisons(ResultDescription result, Map comparisons) { DeltaSummaryStatistics statistics = new DeltaSummaryStatistics(); var tests = new ArrayList<>(result.identifierToResultMap().keySet().stream().map(identifier -> { JPlagComparison comparison = comparisons.get(identifier); @@ -113,7 +162,8 @@ private Collection generateTestsForResultDescription(File resultJso return generateTest(identifier, expectedResult, comparison, statistics); }).toList()); tests.addAll(evaluateDeviationOfSimilarity(statistics)); - return tests; + + return DynamicContainer.dynamicContainer("comparison changes", tests); } /** @@ -137,29 +187,65 @@ private DynamicTest generateTest(String name, ExpectedResult expectedResult, JPl if (expectedResult.resultMatchedTokenNumber() != result.getNumberOfMatchedTokens()) { errors.add(formattedValidationError(INTERSECTION, expectedResult.resultMatchedTokenNumber(), result.getNumberOfMatchedTokens())); } - assertTrue(errors.isEmpty(), createValidationErrorOutput(name, errors)); + assertTrue(errors.isEmpty(), createValidationErrorOutput(name, errors, result)); }); } + /** + * Generates the tests for the gold standard + * @param dataSet The data set + * @param comparisonMap The comparisons + * @param goldStandard The gold standard previously saved + * @return The node containing the tests + */ + private DynamicNode generateGoldStandardTest(DataSet dataSet, Map comparisonMap, GoldStandard goldStandard) + throws IOException { + if (goldStandard != null) { + Set goldStandardIdentifiers = ComparisonIdentifier + .loadIdentifiersFromFile(dataSet.getGoldStandardFile().orElseThrow(), dataSet.getActualDelimiter()); + GoldStandard found = GoldStandard.buildFromComparisons(comparisonMap.values(), goldStandardIdentifiers); + + DynamicTest goldStandardMatch = DynamicTest.dynamicTest("expected plagiarism comparisons average similarity", + () -> assertEquals(goldStandard.matchAverage(), found.matchAverage(), EPSILON, + "expected plagiarism comparisons have deviating similarities")); + + DynamicTest goldStandardNonMatch = DynamicTest.dynamicTest("expected non plagiarism comparisons average", + () -> assertEquals(goldStandard.nonMatchAverage(), found.nonMatchAverage(), EPSILON, + "expected non plagiarism comparisons have deviating similarities")); + + return DynamicContainer.dynamicContainer("expected plagiarism test", List.of(goldStandardMatch, goldStandardNonMatch)); + } else { + return DynamicTest.dynamicTest("expected plagiarisms skipped", + () -> Assumptions.abort("The expected plagiarisms test is skipped, because no expected plagiarisms are defined.")); + } + } + /** * Creates the display message for a result value validation error. - * @param valueName Name of the failed test object + * @param metric The metric the test failed for * @param actualValue actual test value * @param expectedValue expected test value */ private String formattedValidationError(SimilarityMetric metric, Number actualValue, Number expectedValue) { - return metric + " was " + String.valueOf(actualValue) + " but expected " + String.valueOf(expectedValue); + return metric + " was " + actualValue + " but expected " + expectedValue; } /** * Creates the display info from the passed failed test results * @return formatted text for the failed comparative values of the current test */ - private String createValidationErrorOutput(String name, List validationErrors) { + private String createValidationErrorOutput(String name, List validationErrors, JPlagComparison result) { return name + ": There were " + validationErrors.size() + " validation error(s):" + System.lineSeparator() - + String.join(System.lineSeparator(), validationErrors); + + String.join(System.lineSeparator(), validationErrors) + System.lineSeparator() + "First file tokens: " + + String.join(",", getTokenNames(result.firstSubmission())) + System.lineSeparator() + "Second file tokens: " + + String.join(",", getTokenNames(result.secondSubmission())); } + /** + * Creates the tests for the average deviation + * @param deltaStatistics The deltas + * @return The list of tests + */ private List evaluateDeviationOfSimilarity(DeltaSummaryStatistics deltaStatistics) { return List.of(deviationOfSimilarityTest("positive", deltaStatistics.getPositiveStatistics()), deviationOfSimilarityTest("negative", deltaStatistics.getNegativeStatistics())); @@ -168,8 +254,18 @@ private List evaluateDeviationOfSimilarity(DeltaSummaryStatistics d private DynamicTest deviationOfSimilarityTest(String textualSign, DoubleSummaryStatistics statistics) { return DynamicTest.dynamicTest("OVERVIEW: " + textualSign + " similarity deviation", () -> { if (Math.abs(statistics.getAverage()) > EPSILON) { - fail(textualSign + " deviation over all AVG similarity values:" + System.lineSeparator() + statistics.toString()); + fail(textualSign + " deviation over all AVG similarity values:" + System.lineSeparator() + statistics); } }); } + + private List getTokenNames(Submission submission) { + return submission.getTokenList().stream().map(it -> { + if (Enum.class.isAssignableFrom(it.getType().getClass())) { + return ((Enum) it.getType()).name(); + } else { + return it.getType().getDescription(); + } + }).toList(); + } } diff --git a/endtoend-testing/src/test/java/de/jplag/endtoend/architecture/JPlagArchitectureTest.java b/endtoend-testing/src/test/java/de/jplag/endtoend/architecture/JPlagArchitectureTest.java new file mode 100644 index 000000000..4c093148d --- /dev/null +++ b/endtoend-testing/src/test/java/de/jplag/endtoend/architecture/JPlagArchitectureTest.java @@ -0,0 +1,18 @@ +package de.jplag.endtoend.architecture; + +import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.fields; +import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses; + +import com.tngtech.archunit.junit.AnalyzeClasses; +import com.tngtech.archunit.junit.ArchTest; +import com.tngtech.archunit.lang.ArchRule; + +@AnalyzeClasses(packages = "de.jplag") +public class JPlagArchitectureTest { + @ArchTest + public static final ArchRule enforceCorrectLogger = noClasses().should().accessClassesThat() + .haveNameMatching(java.util.logging.Logger.class.getName()); + + @ArchTest + public static final ArchRule enforceNameOfLogger = fields().that().haveRawType(org.slf4j.Logger.class).should().haveName("logger"); +} diff --git a/endtoend-testing/src/test/resources/data/progpedia.zip b/endtoend-testing/src/test/resources/data/progpedia.zip new file mode 100644 index 000000000..01d0859ee Binary files /dev/null and b/endtoend-testing/src/test/resources/data/progpedia.zip differ diff --git a/endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo.java b/endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo.java similarity index 100% rename from endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo.java rename to endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo.java diff --git a/endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo1.java b/endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo1.java similarity index 100% rename from endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo1.java rename to endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo1.java diff --git a/endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo1_2.java b/endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo1_2.java similarity index 100% rename from endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo1_2.java rename to endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo1_2.java diff --git a/endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo1_3.java b/endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo1_3.java similarity index 100% rename from endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo1_3.java rename to endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo1_3.java diff --git a/endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo1_4.java b/endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo1_4.java similarity index 100% rename from endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo1_4.java rename to endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo1_4.java diff --git a/endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo1_5.java b/endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo1_5.java similarity index 100% rename from endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo1_5.java rename to endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo1_5.java diff --git a/endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo1_6.java b/endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo1_6.java similarity index 100% rename from endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo1_6.java rename to endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo1_6.java diff --git a/endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo2.java b/endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo2.java similarity index 100% rename from endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo2.java rename to endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo2.java diff --git a/endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo2_5.java b/endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo2_5.java similarity index 100% rename from endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo2_5.java rename to endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo2_5.java diff --git a/endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo3.java b/endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo3.java similarity index 100% rename from endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo3.java rename to endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo3.java diff --git a/endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo3_5.java b/endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo3_5.java similarity index 100% rename from endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo3_5.java rename to endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo3_5.java diff --git a/endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo3_6.java b/endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo3_6.java similarity index 100% rename from endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo3_6.java rename to endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo3_6.java diff --git a/endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo4.java b/endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo4.java similarity index 100% rename from endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo4.java rename to endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo4.java diff --git a/endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo4d1.java b/endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo4d1.java similarity index 100% rename from endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo4d1.java rename to endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo4d1.java diff --git a/endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo4d2.java b/endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo4d2.java similarity index 100% rename from endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo4d2.java rename to endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo4d2.java diff --git a/endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo4d3.java b/endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo4d3.java similarity index 100% rename from endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo4d3.java rename to endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo4d3.java diff --git a/endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo5.java b/endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo5.java similarity index 100% rename from endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo5.java rename to endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo5.java diff --git a/endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo6.java b/endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo6.java similarity index 100% rename from endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo6.java rename to endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo6.java diff --git a/endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo7.java b/endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo7.java similarity index 100% rename from endtoend-testing/src/test/resources/languageTestFiles/java/sortAlgo/SortAlgo7.java rename to endtoend-testing/src/test/resources/data/sortAlgo/SortAlgo7.java diff --git a/endtoend-testing/src/test/resources/dataSetTemplate.json b/endtoend-testing/src/test/resources/dataSetTemplate.json new file mode 100644 index 000000000..fe10e8d15 --- /dev/null +++ b/endtoend-testing/src/test/resources/dataSetTemplate.json @@ -0,0 +1,13 @@ +{ + "name": "The name of the data set.", + "language": "The language identifier for the data set.", + "format": "The format of the data set. Must be defined in de.jplag.endtoend.model.DataSetFormat.", + "sourceDirectory": "The root directory of the data set. The contents need to match the format.", + "resultFile": "(optional) The path to the result file. If not set defaults to: results/$name.json.", + "goldStandardFile": "(optional) Set to activate the gold standard test.", + "options": { + "_comment": "(optional) Provide to specify options for jplag", + "minimumTokenMatches": [" (optional) add additional minimum token matches to check for the data set. 3 and 9 are always checked."], + "baseCodeDirectory": "(optional) here you can provide the name of the base code directory. The exact path will be resolved using the format" + } +} \ No newline at end of file diff --git a/endtoend-testing/src/test/resources/dataSets/progpedia.json b/endtoend-testing/src/test/resources/dataSets/progpedia.json new file mode 100644 index 000000000..04ce00917 --- /dev/null +++ b/endtoend-testing/src/test/resources/dataSets/progpedia.json @@ -0,0 +1,10 @@ +{ + "name": "progpedia", + "language": "java", + "format": "PROGPEDIA", + "storageFormat": "ZIP", + "goldStandardFile": "plagiarism.csv", + "options": { + "baseCodeDirectory": "base" + } +} \ No newline at end of file diff --git a/endtoend-testing/src/test/resources/dataSets/sortAlgo.json b/endtoend-testing/src/test/resources/dataSets/sortAlgo.json new file mode 100644 index 000000000..6875d569e --- /dev/null +++ b/endtoend-testing/src/test/resources/dataSets/sortAlgo.json @@ -0,0 +1,5 @@ +{ + "name": "sortAlgo", + "language": "java", + "format": "PLAIN" +} \ No newline at end of file diff --git a/endtoend-testing/src/test/resources/results/progpedia.json b/endtoend-testing/src/test/resources/results/progpedia.json new file mode 100644 index 000000000..ec8aad38b --- /dev/null +++ b/endtoend-testing/src/test/resources/results/progpedia.json @@ -0,0 +1,21467 @@ +[ { + "tests" : { + "00113_00002-00141_00002" : { + "minimal_similarity" : 0.5819672131147541, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00092_00001-00197_00001" : { + "minimal_similarity" : 0.48484848484848486, + "maximum_similarity" : 0.5423728813559322, + "matched_token_number" : 64 + }, + "00140_00001-00154_00002" : { + "minimal_similarity" : 0.5630252100840336, + "maximum_similarity" : 0.7701149425287356, + "matched_token_number" : 67 + }, + "00013_00002-00129_00008" : { + "minimal_similarity" : 0.32340425531914896, + "maximum_similarity" : 0.8, + "matched_token_number" : 76 + }, + "00005_00002-00125_00001" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00147_00001-00178_00002" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00000_00002-00119_00001" : { + "minimal_similarity" : 0.4782608695652174, + "maximum_similarity" : 0.5092592592592593, + "matched_token_number" : 55 + }, + "00119_00001-00125_00001" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00141_00002-00194_00001" : { + "minimal_similarity" : 0.9722222222222222, + "maximum_similarity" : 0.9722222222222222, + "matched_token_number" : 105 + }, + "00129_00008-00196_00001" : { + "minimal_similarity" : 0.4037854889589905, + "maximum_similarity" : 0.5446808510638298, + "matched_token_number" : 128 + }, + "00135_00001-00195_00002" : { + "minimal_similarity" : 0.4178082191780822, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00000_00005-00194_00001" : { + "minimal_similarity" : 0.4666666666666667, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 56 + }, + "00145_00001-00160_00001" : { + "minimal_similarity" : 0.6102941176470589, + "maximum_similarity" : 0.6747967479674797, + "matched_token_number" : 83 + }, + "00153_00001-00202_00002" : { + "minimal_similarity" : 0.46808510638297873, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00136_00002-00142_00001" : { + "minimal_similarity" : 0.2722222222222222, + "maximum_similarity" : 0.4152542372881356, + "matched_token_number" : 49 + }, + "00202_00002-00204_00001" : { + "minimal_similarity" : 0.6028368794326241, + "maximum_similarity" : 0.7083333333333334, + "matched_token_number" : 85 + }, + "00135_00001-00195_00001" : { + "minimal_similarity" : 0.4178082191780822, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00031_00002-00160_00001" : { + "minimal_similarity" : 0.35294117647058826, + "maximum_similarity" : 0.5217391304347826, + "matched_token_number" : 48 + }, + "00153_00001-00202_00003" : { + "minimal_similarity" : 0.4326241134751773, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00000_00003-00199_00001" : { + "minimal_similarity" : 0.5294117647058824, + "maximum_similarity" : 0.6631578947368421, + "matched_token_number" : 63 + }, + "00126_00002-00177_00003" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00183_00004-00196_00001" : { + "minimal_similarity" : 0.2744479495268139, + "maximum_similarity" : 0.6170212765957447, + "matched_token_number" : 87 + }, + "00005_00002-00192_00002" : { + "minimal_similarity" : 0.5375, + "maximum_similarity" : 0.6564885496183206, + "matched_token_number" : 86 + }, + "00031_00002-00203_00002" : { + "minimal_similarity" : 0.43795620437956206, + "maximum_similarity" : 0.6521739130434783, + "matched_token_number" : 60 + }, + "00005_00002-00192_00001" : { + "minimal_similarity" : 0.55, + "maximum_similarity" : 0.567741935483871, + "matched_token_number" : 88 + }, + "00177_00003-00192_00001" : { + "minimal_similarity" : 0.44516129032258067, + "maximum_similarity" : 0.5609756097560976, + "matched_token_number" : 69 + }, + "00177_00003-00192_00002" : { + "minimal_similarity" : 0.5267175572519084, + "maximum_similarity" : 0.5609756097560976, + "matched_token_number" : 69 + }, + "00156_00003-00183_00004" : { + "minimal_similarity" : 0.48226950354609927, + "maximum_similarity" : 0.5, + "matched_token_number" : 68 + }, + "00000_00001-00199_00001" : { + "minimal_similarity" : 0.5204081632653061, + "maximum_similarity" : 0.5368421052631579, + "matched_token_number" : 51 + }, + "00145_00001-00186_00002" : { + "minimal_similarity" : 0.4782608695652174, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00145_00001-00186_00004" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.5283018867924528, + "matched_token_number" : 56 + }, + "00125_00001-00137_00002" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00031_00003-00199_00001" : { + "minimal_similarity" : 0.45263157894736844, + "maximum_similarity" : 0.5058823529411764, + "matched_token_number" : 43 + }, + "00138_00001-00147_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 118 + }, + "00134_00001-00142_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.691358024691358, + "matched_token_number" : 56 + }, + "00005_00002-00120_00001" : { + "minimal_similarity" : 0.46875, + "maximum_similarity" : 0.635593220338983, + "matched_token_number" : 75 + }, + "00195_00001-00204_00001" : { + "minimal_similarity" : 0.4666666666666667, + "maximum_similarity" : 0.4745762711864407, + "matched_token_number" : 56 + }, + "00120_00001-00198_00001" : { + "minimal_similarity" : 0.3881578947368421, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00137_00002-00195_00002" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00137_00002-00195_00001" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00155_00001-00177_00003" : { + "minimal_similarity" : 0.5447154471544715, + "maximum_similarity" : 0.7701149425287356, + "matched_token_number" : 67 + }, + "00000_00001-00127_00002" : { + "minimal_similarity" : 0.43902439024390244, + "maximum_similarity" : 0.5510204081632653, + "matched_token_number" : 54 + }, + "00031_00002-00119_00001" : { + "minimal_similarity" : 0.5185185185185185, + "maximum_similarity" : 0.6086956521739131, + "matched_token_number" : 56 + }, + "00097_00002-00195_00002" : { + "minimal_similarity" : 0.4576271186440678, + "maximum_similarity" : 0.5094339622641509, + "matched_token_number" : 54 + }, + "00097_00002-00195_00001" : { + "minimal_similarity" : 0.4576271186440678, + "maximum_similarity" : 0.5094339622641509, + "matched_token_number" : 54 + }, + "00127_00002-00183_00004" : { + "minimal_similarity" : 0.48226950354609927, + "maximum_similarity" : 0.5528455284552846, + "matched_token_number" : 68 + }, + "00000_00002-00160_00001" : { + "minimal_similarity" : 0.47058823529411764, + "maximum_similarity" : 0.5565217391304348, + "matched_token_number" : 64 + }, + "00120_00001-00126_00002" : { + "minimal_similarity" : 0.9830508474576272, + "maximum_similarity" : 0.9830508474576272, + "matched_token_number" : 116 + }, + "00133_00001-00136_00002" : { + "minimal_similarity" : 0.4, + "maximum_similarity" : 0.5853658536585366, + "matched_token_number" : 72 + }, + "00154_00002-00183_00004" : { + "minimal_similarity" : 0.425531914893617, + "maximum_similarity" : 0.5042016806722689, + "matched_token_number" : 60 + }, + "00127_00002-00137_00002" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00014_00001-00202_00002" : { + "minimal_similarity" : 0.475177304964539, + "maximum_similarity" : 0.6203703703703703, + "matched_token_number" : 67 + }, + "00000_00005-00199_00001" : { + "minimal_similarity" : 0.48333333333333334, + "maximum_similarity" : 0.6105263157894737, + "matched_token_number" : 58 + }, + "00134_00001-00201_00001" : { + "minimal_similarity" : 0.367816091954023, + "maximum_similarity" : 0.3950617283950617, + "matched_token_number" : 32 + }, + "00184_00003-00202_00002" : { + "minimal_similarity" : 0.425531914893617, + "maximum_similarity" : 0.6382978723404256, + "matched_token_number" : 60 + }, + "00044_00002-00196_00001" : { + "minimal_similarity" : 0.11041009463722397, + "maximum_similarity" : 0.35353535353535354, + "matched_token_number" : 35 + }, + "00178_00002-00203_00002" : { + "minimal_similarity" : 0.5766423357664233, + "maximum_similarity" : 0.6422764227642277, + "matched_token_number" : 79 + }, + "00184_00003-00202_00003" : { + "minimal_similarity" : 0.4397163120567376, + "maximum_similarity" : 0.6595744680851063, + "matched_token_number" : 62 + }, + "00031_00002-00186_00002" : { + "minimal_similarity" : 0.4057971014492754, + "maximum_similarity" : 0.6086956521739131, + "matched_token_number" : 56 + }, + "00000_00001-00194_00001" : { + "minimal_similarity" : 0.5277777777777778, + "maximum_similarity" : 0.5816326530612245, + "matched_token_number" : 57 + }, + "00031_00002-00186_00004" : { + "minimal_similarity" : 0.4528301886792453, + "maximum_similarity" : 0.5217391304347826, + "matched_token_number" : 48 + }, + "00014_00001-00202_00003" : { + "minimal_similarity" : 0.45390070921985815, + "maximum_similarity" : 0.5925925925925926, + "matched_token_number" : 64 + }, + "00000_00003-00194_00001" : { + "minimal_similarity" : 0.4957983193277311, + "maximum_similarity" : 0.5462962962962963, + "matched_token_number" : 59 + }, + "00119_00001-00120_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 56 + }, + "00013_00002-00014_00001" : { + "minimal_similarity" : 0.5185185185185185, + "maximum_similarity" : 0.5894736842105263, + "matched_token_number" : 56 + }, + "00120_00001-00193_00001" : { + "minimal_similarity" : 0.42857142857142855, + "maximum_similarity" : 0.4830508474576271, + "matched_token_number" : 57 + }, + "00126_00002-00156_00002" : { + "minimal_similarity" : 0.34558823529411764, + "maximum_similarity" : 0.3983050847457627, + "matched_token_number" : 47 + }, + "00126_00002-00156_00003" : { + "minimal_similarity" : 0.34558823529411764, + "maximum_similarity" : 0.3983050847457627, + "matched_token_number" : 47 + }, + "00187_00001-00200_00002" : { + "minimal_similarity" : 0.5454545454545454, + "maximum_similarity" : 0.5581395348837209, + "matched_token_number" : 72 + }, + "00156_00002-00196_00001" : { + "minimal_similarity" : 0.25236593059936907, + "maximum_similarity" : 0.5882352941176471, + "matched_token_number" : 80 + }, + "00077_00001-00154_00002" : { + "minimal_similarity" : 0.49375, + "maximum_similarity" : 0.6638655462184874, + "matched_token_number" : 79 + }, + "00127_00002-00200_00002" : { + "minimal_similarity" : 0.5658914728682171, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00192_00001-00193_00001" : { + "minimal_similarity" : 0.5806451612903226, + "maximum_similarity" : 0.6766917293233082, + "matched_token_number" : 90 + }, + "00120_00001-00121_00001" : { + "minimal_similarity" : 0.4632352941176471, + "maximum_similarity" : 0.5338983050847458, + "matched_token_number" : 63 + }, + "00111_00001-00183_00004" : { + "minimal_similarity" : 0.48226950354609927, + "maximum_similarity" : 0.5528455284552846, + "matched_token_number" : 68 + }, + "00119_00001-00141_00002" : { + "minimal_similarity" : 0.9722222222222222, + "maximum_similarity" : 0.9722222222222222, + "matched_token_number" : 105 + }, + "00031_00003-00127_00002" : { + "minimal_similarity" : 0.43902439024390244, + "maximum_similarity" : 0.6352941176470588, + "matched_token_number" : 54 + }, + "00142_00001-00192_00002" : { + "minimal_similarity" : 0.4580152671755725, + "maximum_similarity" : 0.5084745762711864, + "matched_token_number" : 60 + }, + "00000_00002-00135_00001" : { + "minimal_similarity" : 0.410958904109589, + "maximum_similarity" : 0.5217391304347826, + "matched_token_number" : 60 + }, + "00142_00001-00192_00001" : { + "minimal_similarity" : 0.4129032258064516, + "maximum_similarity" : 0.5423728813559322, + "matched_token_number" : 64 + }, + "00142_00001-00200_00002" : { + "minimal_similarity" : 0.4263565891472868, + "maximum_similarity" : 0.4661016949152542, + "matched_token_number" : 55 + }, + "00130_00002-00192_00002" : { + "minimal_similarity" : 0.4198473282442748, + "maximum_similarity" : 0.632183908045977, + "matched_token_number" : 55 + }, + "00130_00002-00192_00001" : { + "minimal_similarity" : 0.36774193548387096, + "maximum_similarity" : 0.6551724137931034, + "matched_token_number" : 57 + }, + "00077_00001-00095_00003" : { + "minimal_similarity" : 0.37790697674418605, + "maximum_similarity" : 0.40625, + "matched_token_number" : 65 + }, + "00133_00001-00187_00001" : { + "minimal_similarity" : 0.5909090909090909, + "maximum_similarity" : 0.6341463414634146, + "matched_token_number" : 78 + }, + "00130_00002-00155_00001" : { + "minimal_similarity" : 0.5747126436781609, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00147_00001-00199_00001" : { + "minimal_similarity" : 0.3898305084745763, + "maximum_similarity" : 0.4842105263157895, + "matched_token_number" : 46 + }, + "00077_00001-00196_00001" : { + "minimal_similarity" : 0.1640378548895899, + "maximum_similarity" : 0.325, + "matched_token_number" : 52 + }, + "00120_00001-00147_00001" : { + "minimal_similarity" : 0.5338983050847458, + "maximum_similarity" : 0.5338983050847458, + "matched_token_number" : 63 + }, + "00125_00001-00183_00004" : { + "minimal_similarity" : 0.48226950354609927, + "maximum_similarity" : 0.5528455284552846, + "matched_token_number" : 68 + }, + "00113_00002-00125_00001" : { + "minimal_similarity" : 0.943089430894309, + "maximum_similarity" : 0.9508196721311475, + "matched_token_number" : 116 + }, + "00000_00002-00097_00002" : { + "minimal_similarity" : 0.3826086956521739, + "maximum_similarity" : 0.41509433962264153, + "matched_token_number" : 44 + }, + "00013_00002-00044_00002" : { + "minimal_similarity" : 0.45454545454545453, + "maximum_similarity" : 0.47368421052631576, + "matched_token_number" : 45 + }, + "00126_00002-00198_00001" : { + "minimal_similarity" : 0.3881578947368421, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00044_00002-00129_00008" : { + "minimal_similarity" : 0.23829787234042554, + "maximum_similarity" : 0.5656565656565656, + "matched_token_number" : 56 + }, + "00154_00002-00200_00002" : { + "minimal_similarity" : 0.5116279069767442, + "maximum_similarity" : 0.5546218487394958, + "matched_token_number" : 66 + }, + "00178_00002-00195_00001" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00121_00001-00183_00004" : { + "minimal_similarity" : 0.48936170212765956, + "maximum_similarity" : 0.5073529411764706, + "matched_token_number" : 69 + }, + "00186_00002-00199_00001" : { + "minimal_similarity" : 0.39855072463768115, + "maximum_similarity" : 0.5789473684210527, + "matched_token_number" : 55 + }, + "00121_00001-00153_00001" : { + "minimal_similarity" : 0.6985294117647058, + "maximum_similarity" : 0.7723577235772358, + "matched_token_number" : 95 + }, + "00092_00001-00192_00002" : { + "minimal_similarity" : 0.44274809160305345, + "maximum_similarity" : 0.4915254237288136, + "matched_token_number" : 58 + }, + "00092_00001-00192_00001" : { + "minimal_similarity" : 0.38064516129032255, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00160_00001-00204_00001" : { + "minimal_similarity" : 0.5441176470588235, + "maximum_similarity" : 0.6166666666666667, + "matched_token_number" : 74 + }, + "00111_00001-00125_00001" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00193_00001-00195_00001" : { + "minimal_similarity" : 0.42857142857142855, + "maximum_similarity" : 0.4830508474576271, + "matched_token_number" : 57 + }, + "00178_00002-00195_00002" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00095_00003-00160_00001" : { + "minimal_similarity" : 0.436046511627907, + "maximum_similarity" : 0.5514705882352942, + "matched_token_number" : 75 + }, + "00193_00001-00195_00002" : { + "minimal_similarity" : 0.42857142857142855, + "maximum_similarity" : 0.4830508474576271, + "matched_token_number" : 57 + }, + "00130_00002-00134_00001" : { + "minimal_similarity" : 0.632183908045977, + "maximum_similarity" : 0.6790123456790124, + "matched_token_number" : 55 + }, + "00000_00002-00186_00004" : { + "minimal_similarity" : 0.4260869565217391, + "maximum_similarity" : 0.46226415094339623, + "matched_token_number" : 49 + }, + "00119_00001-00192_00001" : { + "minimal_similarity" : 0.41935483870967744, + "maximum_similarity" : 0.6018518518518519, + "matched_token_number" : 65 + }, + "00119_00001-00192_00002" : { + "minimal_similarity" : 0.5190839694656488, + "maximum_similarity" : 0.6296296296296297, + "matched_token_number" : 68 + }, + "00031_00003-00178_00002" : { + "minimal_similarity" : 0.43902439024390244, + "maximum_similarity" : 0.6352941176470588, + "matched_token_number" : 54 + }, + "00000_00002-00186_00002" : { + "minimal_similarity" : 0.4420289855072464, + "maximum_similarity" : 0.5304347826086957, + "matched_token_number" : 61 + }, + "00136_00002-00147_00001" : { + "minimal_similarity" : 0.4111111111111111, + "maximum_similarity" : 0.6271186440677966, + "matched_token_number" : 74 + }, + "00005_00002-00197_00001" : { + "minimal_similarity" : 0.49375, + "maximum_similarity" : 0.5984848484848485, + "matched_token_number" : 79 + }, + "00156_00003-00200_00002" : { + "minimal_similarity" : 0.4117647058823529, + "maximum_similarity" : 0.43410852713178294, + "matched_token_number" : 56 + }, + "00177_00003-00197_00001" : { + "minimal_similarity" : 0.5909090909090909, + "maximum_similarity" : 0.6341463414634146, + "matched_token_number" : 78 + }, + "00155_00001-00156_00002" : { + "minimal_similarity" : 0.38235294117647056, + "maximum_similarity" : 0.5977011494252874, + "matched_token_number" : 52 + }, + "00031_00003-00131_00005" : { + "minimal_similarity" : 0.3375, + "maximum_similarity" : 0.6352941176470588, + "matched_token_number" : 54 + }, + "00129_00008-00145_00001" : { + "minimal_similarity" : 0.3191489361702128, + "maximum_similarity" : 0.6097560975609756, + "matched_token_number" : 75 + }, + "00126_00002-00130_00002" : { + "minimal_similarity" : 0.4406779661016949, + "maximum_similarity" : 0.5977011494252874, + "matched_token_number" : 52 + }, + "00155_00001-00156_00003" : { + "minimal_similarity" : 0.38235294117647056, + "maximum_similarity" : 0.5977011494252874, + "matched_token_number" : 52 + }, + "00113_00002-00183_00004" : { + "minimal_similarity" : 0.48226950354609927, + "maximum_similarity" : 0.5573770491803278, + "matched_token_number" : 68 + }, + "00140_00001-00196_00001" : { + "minimal_similarity" : 0.10725552050473186, + "maximum_similarity" : 0.39080459770114945, + "matched_token_number" : 34 + }, + "00134_00001-00147_00001" : { + "minimal_similarity" : 0.3050847457627119, + "maximum_similarity" : 0.4444444444444444, + "matched_token_number" : 36 + }, + "00138_00001-00177_00003" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00186_00004-00199_00001" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.5578947368421052, + "matched_token_number" : 53 + }, + "00192_00002-00197_00001" : { + "minimal_similarity" : 0.7878787878787878, + "maximum_similarity" : 0.7938931297709924, + "matched_token_number" : 104 + }, + "00184_00002-00186_00002" : { + "minimal_similarity" : 0.4057971014492754, + "maximum_similarity" : 0.5957446808510638, + "matched_token_number" : 56 + }, + "00092_00001-00134_00001" : { + "minimal_similarity" : 0.3050847457627119, + "maximum_similarity" : 0.4444444444444444, + "matched_token_number" : 36 + }, + "00183_00004-00204_00001" : { + "minimal_similarity" : 0.5602836879432624, + "maximum_similarity" : 0.6583333333333333, + "matched_token_number" : 79 + }, + "00184_00002-00186_00004" : { + "minimal_similarity" : 0.5094339622641509, + "maximum_similarity" : 0.574468085106383, + "matched_token_number" : 54 + }, + "00014_00001-00199_00001" : { + "minimal_similarity" : 0.5092592592592593, + "maximum_similarity" : 0.5789473684210527, + "matched_token_number" : 55 + }, + "00097_00002-00160_00001" : { + "minimal_similarity" : 0.41911764705882354, + "maximum_similarity" : 0.5377358490566038, + "matched_token_number" : 57 + }, + "00131_00005-00153_00001" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00131_00005-00186_00004" : { + "minimal_similarity" : 0.39375, + "maximum_similarity" : 0.5943396226415094, + "matched_token_number" : 63 + }, + "00095_00003-00119_00001" : { + "minimal_similarity" : 0.313953488372093, + "maximum_similarity" : 0.5, + "matched_token_number" : 54 + }, + "00119_00001-00200_00002" : { + "minimal_similarity" : 0.5193798449612403, + "maximum_similarity" : 0.6203703703703703, + "matched_token_number" : 67 + }, + "00000_00003-00000_00005" : { + "minimal_similarity" : 0.9333333333333333, + "maximum_similarity" : 0.9411764705882353, + "matched_token_number" : 112 + }, + "00119_00001-00155_00001" : { + "minimal_similarity" : 0.5370370370370371, + "maximum_similarity" : 0.6666666666666666, + "matched_token_number" : 58 + }, + "00131_00005-00186_00002" : { + "minimal_similarity" : 0.4125, + "maximum_similarity" : 0.4782608695652174, + "matched_token_number" : 66 + }, + "00129_00008-00133_00001" : { + "minimal_similarity" : 0.3191489361702128, + "maximum_similarity" : 0.6097560975609756, + "matched_token_number" : 75 + }, + "00097_00002-00153_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5754716981132075, + "matched_token_number" : 61 + }, + "00000_00002-00013_00002" : { + "minimal_similarity" : 0.3826086956521739, + "maximum_similarity" : 0.4631578947368421, + "matched_token_number" : 44 + }, + "00127_00002-00141_00002" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00031_00002-00092_00001" : { + "minimal_similarity" : 0.4067796610169492, + "maximum_similarity" : 0.5217391304347826, + "matched_token_number" : 48 + }, + "00000_00005-00131_00005" : { + "minimal_similarity" : 0.3875, + "maximum_similarity" : 0.5166666666666667, + "matched_token_number" : 62 + }, + "00184_00003-00199_00001" : { + "minimal_similarity" : 0.9789473684210527, + "maximum_similarity" : 0.9893617021276596, + "matched_token_number" : 93 + }, + "00044_00002-00095_00003" : { + "minimal_similarity" : 0.3081395348837209, + "maximum_similarity" : 0.5353535353535354, + "matched_token_number" : 53 + }, + "00113_00002-00197_00001" : { + "minimal_similarity" : 0.5909090909090909, + "maximum_similarity" : 0.639344262295082, + "matched_token_number" : 78 + }, + "00044_00002-00138_00001" : { + "minimal_similarity" : 0.3813559322033898, + "maximum_similarity" : 0.45454545454545453, + "matched_token_number" : 45 + }, + "00000_00001-00136_00002" : { + "minimal_similarity" : 0.2833333333333333, + "maximum_similarity" : 0.5204081632653061, + "matched_token_number" : 51 + }, + "00129_00008-00140_00001" : { + "minimal_similarity" : 0.20425531914893616, + "maximum_similarity" : 0.5517241379310345, + "matched_token_number" : 48 + }, + "00133_00001-00145_00001" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00031_00003-00136_00002" : { + "minimal_similarity" : 0.35, + "maximum_similarity" : 0.7411764705882353, + "matched_token_number" : 63 + }, + "00141_00002-00202_00003" : { + "minimal_similarity" : 0.45390070921985815, + "maximum_similarity" : 0.5925925925925926, + "matched_token_number" : 64 + }, + "00005_00002-00155_00001" : { + "minimal_similarity" : 0.3125, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00192_00002-00202_00002" : { + "minimal_similarity" : 0.7446808510638298, + "maximum_similarity" : 0.8015267175572519, + "matched_token_number" : 105 + }, + "00141_00002-00202_00002" : { + "minimal_similarity" : 0.475177304964539, + "maximum_similarity" : 0.6203703703703703, + "matched_token_number" : 67 + }, + "00031_00002-00156_00003" : { + "minimal_similarity" : 0.33088235294117646, + "maximum_similarity" : 0.4891304347826087, + "matched_token_number" : 45 + }, + "00014_00001-00194_00001" : { + "minimal_similarity" : 0.9722222222222222, + "maximum_similarity" : 0.9722222222222222, + "matched_token_number" : 105 + }, + "00031_00002-00156_00002" : { + "minimal_similarity" : 0.33088235294117646, + "maximum_similarity" : 0.4891304347826087, + "matched_token_number" : 45 + }, + "00138_00001-00184_00003" : { + "minimal_similarity" : 0.3983050847457627, + "maximum_similarity" : 0.5, + "matched_token_number" : 47 + }, + "00192_00002-00202_00003" : { + "minimal_similarity" : 0.7730496453900709, + "maximum_similarity" : 0.8320610687022901, + "matched_token_number" : 109 + }, + "00044_00002-00204_00001" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.6060606060606061, + "matched_token_number" : 60 + }, + "00111_00001-00192_00002" : { + "minimal_similarity" : 0.5267175572519084, + "maximum_similarity" : 0.5609756097560976, + "matched_token_number" : 69 + }, + "00000_00001-00202_00002" : { + "minimal_similarity" : 0.3971631205673759, + "maximum_similarity" : 0.5714285714285714, + "matched_token_number" : 56 + }, + "00138_00001-00184_00002" : { + "minimal_similarity" : 0.3983050847457627, + "maximum_similarity" : 0.5, + "matched_token_number" : 47 + }, + "00111_00001-00192_00001" : { + "minimal_similarity" : 0.44516129032258067, + "maximum_similarity" : 0.5609756097560976, + "matched_token_number" : 69 + }, + "00000_00001-00202_00003" : { + "minimal_similarity" : 0.36879432624113473, + "maximum_similarity" : 0.5306122448979592, + "matched_token_number" : 52 + }, + "00183_00004-00187_00001" : { + "minimal_similarity" : 0.5886524822695035, + "maximum_similarity" : 0.6287878787878788, + "matched_token_number" : 83 + }, + "00000_00002-00130_00002" : { + "minimal_similarity" : 0.45217391304347826, + "maximum_similarity" : 0.5977011494252874, + "matched_token_number" : 52 + }, + "00126_00002-00186_00004" : { + "minimal_similarity" : 0.423728813559322, + "maximum_similarity" : 0.4716981132075472, + "matched_token_number" : 50 + }, + "00031_00003-00077_00001" : { + "minimal_similarity" : 0.3375, + "maximum_similarity" : 0.6352941176470588, + "matched_token_number" : 54 + }, + "00153_00001-00199_00001" : { + "minimal_similarity" : 0.5121951219512195, + "maximum_similarity" : 0.6631578947368421, + "matched_token_number" : 63 + }, + "00126_00002-00186_00002" : { + "minimal_similarity" : 0.3695652173913043, + "maximum_similarity" : 0.4322033898305085, + "matched_token_number" : 51 + }, + "00160_00001-00199_00001" : { + "minimal_similarity" : 0.5073529411764706, + "maximum_similarity" : 0.7263157894736842, + "matched_token_number" : 69 + }, + "00014_00001-00134_00001" : { + "minimal_similarity" : 0.4722222222222222, + "maximum_similarity" : 0.6296296296296297, + "matched_token_number" : 51 + }, + "00133_00001-00199_00001" : { + "minimal_similarity" : 0.5121951219512195, + "maximum_similarity" : 0.6631578947368421, + "matched_token_number" : 63 + }, + "00000_00003-00005_00002" : { + "minimal_similarity" : 0.40625, + "maximum_similarity" : 0.5462184873949579, + "matched_token_number" : 65 + }, + "00127_00002-00153_00001" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00113_00002-00192_00001" : { + "minimal_similarity" : 0.44516129032258067, + "maximum_similarity" : 0.5655737704918032, + "matched_token_number" : 69 + }, + "00133_00001-00204_00001" : { + "minimal_similarity" : 0.5447154471544715, + "maximum_similarity" : 0.5583333333333333, + "matched_token_number" : 67 + }, + "00113_00002-00192_00002" : { + "minimal_similarity" : 0.5267175572519084, + "maximum_similarity" : 0.5655737704918032, + "matched_token_number" : 69 + }, + "00044_00002-00145_00001" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.5656565656565656, + "matched_token_number" : 56 + }, + "00142_00001-00183_00004" : { + "minimal_similarity" : 0.3404255319148936, + "maximum_similarity" : 0.4067796610169492, + "matched_token_number" : 48 + }, + "00125_00001-00200_00002" : { + "minimal_similarity" : 0.5658914728682171, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00129_00008-00138_00001" : { + "minimal_similarity" : 0.30638297872340425, + "maximum_similarity" : 0.6101694915254238, + "matched_token_number" : 72 + }, + "00125_00001-00153_00001" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00178_00002-00186_00002" : { + "minimal_similarity" : 0.4782608695652174, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00000_00001-00131_00005" : { + "minimal_similarity" : 0.3875, + "maximum_similarity" : 0.6326530612244898, + "matched_token_number" : 62 + }, + "00138_00001-00198_00001" : { + "minimal_similarity" : 0.5131578947368421, + "maximum_similarity" : 0.6610169491525424, + "matched_token_number" : 78 + }, + "00000_00005-00136_00002" : { + "minimal_similarity" : 0.3277777777777778, + "maximum_similarity" : 0.49166666666666664, + "matched_token_number" : 59 + }, + "00178_00002-00186_00004" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.5283018867924528, + "matched_token_number" : 56 + }, + "00014_00001-00127_00002" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00192_00001-00201_00001" : { + "minimal_similarity" : 0.2645161290322581, + "maximum_similarity" : 0.47126436781609193, + "matched_token_number" : 41 + }, + "00000_00002-00177_00003" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.48695652173913045, + "matched_token_number" : 56 + }, + "00125_00001-00141_00002" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00092_00001-00120_00001" : { + "minimal_similarity" : 0.5338983050847458, + "maximum_similarity" : 0.5338983050847458, + "matched_token_number" : 63 + }, + "00111_00001-00197_00001" : { + "minimal_similarity" : 0.5909090909090909, + "maximum_similarity" : 0.6341463414634146, + "matched_token_number" : 78 + }, + "00154_00002-00195_00001" : { + "minimal_similarity" : 0.5294117647058824, + "maximum_similarity" : 0.5338983050847458, + "matched_token_number" : 63 + }, + "00136_00002-00156_00003" : { + "minimal_similarity" : 0.4, + "maximum_similarity" : 0.5294117647058824, + "matched_token_number" : 72 + }, + "00131_00005-00203_00002" : { + "minimal_similarity" : 0.48125, + "maximum_similarity" : 0.5620437956204379, + "matched_token_number" : 77 + }, + "00197_00001-00200_00002" : { + "minimal_similarity" : 0.5454545454545454, + "maximum_similarity" : 0.5581395348837209, + "matched_token_number" : 72 + }, + "00154_00002-00195_00002" : { + "minimal_similarity" : 0.5294117647058824, + "maximum_similarity" : 0.5338983050847458, + "matched_token_number" : 63 + }, + "00198_00001-00202_00002" : { + "minimal_similarity" : 0.5855263157894737, + "maximum_similarity" : 0.6312056737588653, + "matched_token_number" : 89 + }, + "00198_00001-00202_00003" : { + "minimal_similarity" : 0.6052631578947368, + "maximum_similarity" : 0.6524822695035462, + "matched_token_number" : 92 + }, + "00031_00003-00202_00002" : { + "minimal_similarity" : 0.36879432624113473, + "maximum_similarity" : 0.611764705882353, + "matched_token_number" : 52 + }, + "00031_00003-00202_00003" : { + "minimal_similarity" : 0.36879432624113473, + "maximum_similarity" : 0.611764705882353, + "matched_token_number" : 52 + }, + "00000_00005-00178_00002" : { + "minimal_similarity" : 0.4634146341463415, + "maximum_similarity" : 0.475, + "matched_token_number" : 57 + }, + "00031_00003-00187_00001" : { + "minimal_similarity" : 0.4166666666666667, + "maximum_similarity" : 0.6470588235294118, + "matched_token_number" : 55 + }, + "00186_00002-00194_00001" : { + "minimal_similarity" : 0.39855072463768115, + "maximum_similarity" : 0.5092592592592593, + "matched_token_number" : 55 + }, + "00005_00002-00111_00001" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00000_00001-00178_00002" : { + "minimal_similarity" : 0.43902439024390244, + "maximum_similarity" : 0.5510204081632653, + "matched_token_number" : 54 + }, + "00126_00002-00135_00001" : { + "minimal_similarity" : 0.4178082191780822, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00131_00005-00137_00002" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00186_00002-00202_00003" : { + "minimal_similarity" : 0.6453900709219859, + "maximum_similarity" : 0.6594202898550725, + "matched_token_number" : 91 + }, + "00186_00002-00202_00002" : { + "minimal_similarity" : 0.6312056737588653, + "maximum_similarity" : 0.644927536231884, + "matched_token_number" : 89 + }, + "00138_00001-00193_00001" : { + "minimal_similarity" : 0.45864661654135336, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00119_00001-00197_00001" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.6111111111111112, + "matched_token_number" : 66 + }, + "00113_00002-00200_00002" : { + "minimal_similarity" : 0.5658914728682171, + "maximum_similarity" : 0.5983606557377049, + "matched_token_number" : 73 + }, + "00092_00001-00125_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00129_00008-00187_00001" : { + "minimal_similarity" : 0.37446808510638296, + "maximum_similarity" : 0.6666666666666666, + "matched_token_number" : 88 + }, + "00131_00005-00135_00001" : { + "minimal_similarity" : 0.45625, + "maximum_similarity" : 0.5, + "matched_token_number" : 73 + }, + "00131_00005-00195_00002" : { + "minimal_similarity" : 0.46875, + "maximum_similarity" : 0.635593220338983, + "matched_token_number" : 75 + }, + "00000_00001-00077_00001" : { + "minimal_similarity" : 0.3875, + "maximum_similarity" : 0.6326530612244898, + "matched_token_number" : 62 + }, + "00000_00005-00077_00001" : { + "minimal_similarity" : 0.3875, + "maximum_similarity" : 0.5166666666666667, + "matched_token_number" : 62 + }, + "00127_00002-00195_00001" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00131_00005-00195_00001" : { + "minimal_similarity" : 0.46875, + "maximum_similarity" : 0.635593220338983, + "matched_token_number" : 75 + }, + "00044_00002-00154_00002" : { + "minimal_similarity" : 0.48739495798319327, + "maximum_similarity" : 0.5858585858585859, + "matched_token_number" : 58 + }, + "00127_00002-00195_00002" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00031_00002-00097_00002" : { + "minimal_similarity" : 0.5471698113207547, + "maximum_similarity" : 0.6304347826086957, + "matched_token_number" : 58 + }, + "00120_00001-00156_00002" : { + "minimal_similarity" : 0.34558823529411764, + "maximum_similarity" : 0.3983050847457627, + "matched_token_number" : 47 + }, + "00111_00001-00200_00002" : { + "minimal_similarity" : 0.5658914728682171, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00120_00001-00156_00003" : { + "minimal_similarity" : 0.34558823529411764, + "maximum_similarity" : 0.3983050847457627, + "matched_token_number" : 47 + }, + "00129_00008-00184_00002" : { + "minimal_similarity" : 0.23829787234042554, + "maximum_similarity" : 0.5957446808510638, + "matched_token_number" : 56 + }, + "00129_00008-00184_00003" : { + "minimal_similarity" : 0.23829787234042554, + "maximum_similarity" : 0.5957446808510638, + "matched_token_number" : 56 + }, + "00000_00005-00127_00002" : { + "minimal_similarity" : 0.4634146341463415, + "maximum_similarity" : 0.475, + "matched_token_number" : 57 + }, + "00199_00001-00204_00001" : { + "minimal_similarity" : 0.5333333333333333, + "maximum_similarity" : 0.6736842105263158, + "matched_token_number" : 64 + }, + "00138_00001-00201_00001" : { + "minimal_similarity" : 0.2966101694915254, + "maximum_similarity" : 0.40229885057471265, + "matched_token_number" : 35 + }, + "00138_00001-00142_00001" : { + "minimal_similarity" : 0.5338983050847458, + "maximum_similarity" : 0.5338983050847458, + "matched_token_number" : 63 + }, + "00125_00001-00195_00002" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00125_00001-00195_00001" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00111_00001-00141_00002" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00141_00002-00199_00001" : { + "minimal_similarity" : 0.5092592592592593, + "maximum_similarity" : 0.5789473684210527, + "matched_token_number" : 55 + }, + "00145_00001-00195_00002" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00097_00002-00203_00002" : { + "minimal_similarity" : 0.43795620437956206, + "maximum_similarity" : 0.5660377358490566, + "matched_token_number" : 60 + }, + "00145_00001-00195_00001" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00192_00001-00198_00001" : { + "minimal_similarity" : 0.6258064516129033, + "maximum_similarity" : 0.6381578947368421, + "matched_token_number" : 97 + }, + "00126_00002-00142_00001" : { + "minimal_similarity" : 0.9830508474576272, + "maximum_similarity" : 0.9830508474576272, + "matched_token_number" : 116 + }, + "00113_00002-00137_00002" : { + "minimal_similarity" : 0.943089430894309, + "maximum_similarity" : 0.9508196721311475, + "matched_token_number" : 116 + }, + "00153_00001-00155_00001" : { + "minimal_similarity" : 0.5447154471544715, + "maximum_similarity" : 0.7701149425287356, + "matched_token_number" : 67 + }, + "00145_00001-00203_00002" : { + "minimal_similarity" : 0.5766423357664233, + "maximum_similarity" : 0.6422764227642277, + "matched_token_number" : 79 + }, + "00127_00002-00197_00001" : { + "minimal_similarity" : 0.5909090909090909, + "maximum_similarity" : 0.6341463414634146, + "matched_token_number" : 78 + }, + "00126_00002-00193_00001" : { + "minimal_similarity" : 0.42857142857142855, + "maximum_similarity" : 0.4830508474576271, + "matched_token_number" : 57 + }, + "00031_00003-00194_00001" : { + "minimal_similarity" : 0.5092592592592593, + "maximum_similarity" : 0.6470588235294118, + "matched_token_number" : 55 + }, + "00111_00001-00137_00002" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00156_00002-00201_00001" : { + "minimal_similarity" : 0.375, + "maximum_similarity" : 0.5862068965517241, + "matched_token_number" : 51 + }, + "00129_00008-00136_00002" : { + "minimal_similarity" : 0.2851063829787234, + "maximum_similarity" : 0.37222222222222223, + "matched_token_number" : 67 + }, + "00097_00002-00130_00002" : { + "minimal_similarity" : 0.42452830188679247, + "maximum_similarity" : 0.5172413793103449, + "matched_token_number" : 45 + }, + "00126_00002-00184_00002" : { + "minimal_similarity" : 0.4661016949152542, + "maximum_similarity" : 0.5851063829787234, + "matched_token_number" : 55 + }, + "00077_00001-00187_00001" : { + "minimal_similarity" : 0.49375, + "maximum_similarity" : 0.5984848484848485, + "matched_token_number" : 79 + }, + "00126_00002-00184_00003" : { + "minimal_similarity" : 0.4661016949152542, + "maximum_similarity" : 0.5851063829787234, + "matched_token_number" : 55 + }, + "00092_00001-00137_00002" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00135_00001-00200_00002" : { + "minimal_similarity" : 0.4863013698630137, + "maximum_similarity" : 0.5503875968992248, + "matched_token_number" : 71 + }, + "00177_00003-00202_00003" : { + "minimal_similarity" : 0.4326241134751773, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00140_00001-00147_00001" : { + "minimal_similarity" : 0.423728813559322, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00097_00002-00183_00004" : { + "minimal_similarity" : 0.40425531914893614, + "maximum_similarity" : 0.5377358490566038, + "matched_token_number" : 57 + }, + "00031_00003-00140_00001" : { + "minimal_similarity" : 0.5747126436781609, + "maximum_similarity" : 0.5882352941176471, + "matched_token_number" : 50 + }, + "00154_00002-00197_00001" : { + "minimal_similarity" : 0.5833333333333334, + "maximum_similarity" : 0.6470588235294118, + "matched_token_number" : 77 + }, + "00141_00002-00187_00001" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.6111111111111112, + "matched_token_number" : 66 + }, + "00013_00002-00201_00001" : { + "minimal_similarity" : 0.42105263157894735, + "maximum_similarity" : 0.45977011494252873, + "matched_token_number" : 40 + }, + "00095_00003-00183_00004" : { + "minimal_similarity" : 0.37790697674418605, + "maximum_similarity" : 0.46099290780141844, + "matched_token_number" : 65 + }, + "00000_00002-00121_00001" : { + "minimal_similarity" : 0.36764705882352944, + "maximum_similarity" : 0.43478260869565216, + "matched_token_number" : 50 + }, + "00031_00002-00153_00001" : { + "minimal_similarity" : 0.4634146341463415, + "maximum_similarity" : 0.6195652173913043, + "matched_token_number" : 57 + }, + "00177_00003-00202_00002" : { + "minimal_similarity" : 0.46808510638297873, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00000_00005-00187_00001" : { + "minimal_similarity" : 0.44696969696969696, + "maximum_similarity" : 0.49166666666666664, + "matched_token_number" : 59 + }, + "00044_00002-00201_00001" : { + "minimal_similarity" : 0.24242424242424243, + "maximum_similarity" : 0.27586206896551724, + "matched_token_number" : 24 + }, + "00111_00001-00195_00001" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00111_00001-00195_00002" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00183_00004-00184_00003" : { + "minimal_similarity" : 0.375886524822695, + "maximum_similarity" : 0.5638297872340425, + "matched_token_number" : 53 + }, + "00183_00004-00184_00002" : { + "minimal_similarity" : 0.375886524822695, + "maximum_similarity" : 0.5638297872340425, + "matched_token_number" : 53 + }, + "00126_00002-00201_00001" : { + "minimal_similarity" : 0.3389830508474576, + "maximum_similarity" : 0.45977011494252873, + "matched_token_number" : 40 + }, + "00131_00005-00183_00004" : { + "minimal_similarity" : 0.44375, + "maximum_similarity" : 0.5035460992907801, + "matched_token_number" : 71 + }, + "00119_00001-00153_00001" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00120_00001-00138_00001" : { + "minimal_similarity" : 0.5338983050847458, + "maximum_similarity" : 0.5338983050847458, + "matched_token_number" : 63 + }, + "00125_00001-00192_00001" : { + "minimal_similarity" : 0.44516129032258067, + "maximum_similarity" : 0.5609756097560976, + "matched_token_number" : 69 + }, + "00125_00001-00192_00002" : { + "minimal_similarity" : 0.5267175572519084, + "maximum_similarity" : 0.5609756097560976, + "matched_token_number" : 69 + }, + "00121_00001-00186_00002" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.5073529411764706, + "matched_token_number" : 69 + }, + "00140_00001-00142_00001" : { + "minimal_similarity" : 0.4406779661016949, + "maximum_similarity" : 0.5977011494252874, + "matched_token_number" : 52 + }, + "00095_00003-00137_00002" : { + "minimal_similarity" : 0.42441860465116277, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00184_00002-00184_00003" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 94 + }, + "00145_00001-00198_00001" : { + "minimal_similarity" : 0.4342105263157895, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00000_00002-00153_00001" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.48695652173913045, + "matched_token_number" : 56 + }, + "00119_00001-00202_00003" : { + "minimal_similarity" : 0.45390070921985815, + "maximum_similarity" : 0.5925925925925926, + "matched_token_number" : 64 + }, + "00121_00001-00186_00004" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.5754716981132075, + "matched_token_number" : 61 + }, + "00000_00001-00113_00002" : { + "minimal_similarity" : 0.4426229508196721, + "maximum_similarity" : 0.5510204081632653, + "matched_token_number" : 54 + }, + "00134_00001-00196_00001" : { + "minimal_similarity" : 0.11356466876971609, + "maximum_similarity" : 0.4444444444444444, + "matched_token_number" : 36 + }, + "00119_00001-00202_00002" : { + "minimal_similarity" : 0.475177304964539, + "maximum_similarity" : 0.6203703703703703, + "matched_token_number" : 67 + }, + "00140_00001-00193_00001" : { + "minimal_similarity" : 0.41353383458646614, + "maximum_similarity" : 0.632183908045977, + "matched_token_number" : 55 + }, + "00111_00001-00134_00001" : { + "minimal_similarity" : 0.4715447154471545, + "maximum_similarity" : 0.7160493827160493, + "matched_token_number" : 58 + }, + "00095_00003-00130_00002" : { + "minimal_similarity" : 0.25, + "maximum_similarity" : 0.4942528735632184, + "matched_token_number" : 43 + }, + "00138_00001-00186_00002" : { + "minimal_similarity" : 0.3695652173913043, + "maximum_similarity" : 0.4322033898305085, + "matched_token_number" : 51 + }, + "00130_00002-00200_00002" : { + "minimal_similarity" : 0.43410852713178294, + "maximum_similarity" : 0.6436781609195402, + "matched_token_number" : 56 + }, + "00138_00001-00186_00004" : { + "minimal_similarity" : 0.423728813559322, + "maximum_similarity" : 0.4716981132075472, + "matched_token_number" : 50 + }, + "00135_00001-00141_00002" : { + "minimal_similarity" : 0.4589041095890411, + "maximum_similarity" : 0.6203703703703703, + "matched_token_number" : 67 + }, + "00092_00001-00183_00004" : { + "minimal_similarity" : 0.3829787234042553, + "maximum_similarity" : 0.4576271186440678, + "matched_token_number" : 54 + }, + "00097_00002-00137_00002" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5754716981132075, + "matched_token_number" : 61 + }, + "00000_00003-00145_00001" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.47058823529411764, + "matched_token_number" : 56 + }, + "00136_00002-00156_00002" : { + "minimal_similarity" : 0.4, + "maximum_similarity" : 0.5294117647058824, + "matched_token_number" : 72 + }, + "00126_00002-00203_00002" : { + "minimal_similarity" : 0.45255474452554745, + "maximum_similarity" : 0.5254237288135594, + "matched_token_number" : 62 + }, + "00133_00001-00194_00001" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00137_00002-00183_00004" : { + "minimal_similarity" : 0.48226950354609927, + "maximum_similarity" : 0.5528455284552846, + "matched_token_number" : 68 + }, + "00000_00001-00145_00001" : { + "minimal_similarity" : 0.43902439024390244, + "maximum_similarity" : 0.5510204081632653, + "matched_token_number" : 54 + }, + "00195_00002-00200_00002" : { + "minimal_similarity" : 0.4263565891472868, + "maximum_similarity" : 0.4661016949152542, + "matched_token_number" : 55 + }, + "00031_00002-00137_00002" : { + "minimal_similarity" : 0.4634146341463415, + "maximum_similarity" : 0.6195652173913043, + "matched_token_number" : 57 + }, + "00138_00001-00160_00001" : { + "minimal_similarity" : 0.45588235294117646, + "maximum_similarity" : 0.5254237288135594, + "matched_token_number" : 62 + }, + "00013_00002-00178_00002" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.6421052631578947, + "matched_token_number" : 61 + }, + "00195_00002-00203_00002" : { + "minimal_similarity" : 0.45255474452554745, + "maximum_similarity" : 0.5254237288135594, + "matched_token_number" : 62 + }, + "00137_00002-00186_00004" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.5283018867924528, + "matched_token_number" : 56 + }, + "00137_00002-00186_00002" : { + "minimal_similarity" : 0.4782608695652174, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00095_00003-00097_00002" : { + "minimal_similarity" : 0.36627906976744184, + "maximum_similarity" : 0.5943396226415094, + "matched_token_number" : 63 + }, + "00014_00001-00155_00001" : { + "minimal_similarity" : 0.5370370370370371, + "maximum_similarity" : 0.6666666666666666, + "matched_token_number" : 58 + }, + "00095_00003-00135_00001" : { + "minimal_similarity" : 0.5290697674418605, + "maximum_similarity" : 0.6232876712328768, + "matched_token_number" : 91 + }, + "00014_00001-00178_00002" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00184_00003-00197_00001" : { + "minimal_similarity" : 0.5227272727272727, + "maximum_similarity" : 0.7340425531914894, + "matched_token_number" : 69 + }, + "00000_00005-00014_00001" : { + "minimal_similarity" : 0.4666666666666667, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 56 + }, + "00126_00002-00160_00001" : { + "minimal_similarity" : 0.47058823529411764, + "maximum_similarity" : 0.5423728813559322, + "matched_token_number" : 64 + }, + "00134_00001-00177_00003" : { + "minimal_similarity" : 0.4715447154471545, + "maximum_similarity" : 0.7160493827160493, + "matched_token_number" : 58 + }, + "00000_00003-00014_00001" : { + "minimal_similarity" : 0.4957983193277311, + "maximum_similarity" : 0.5462962962962963, + "matched_token_number" : 59 + }, + "00156_00002-00178_00002" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00131_00005-00198_00001" : { + "minimal_similarity" : 0.49375, + "maximum_similarity" : 0.5197368421052632, + "matched_token_number" : 79 + }, + "00127_00002-00160_00001" : { + "minimal_similarity" : 0.6102941176470589, + "maximum_similarity" : 0.6747967479674797, + "matched_token_number" : 83 + }, + "00140_00001-00198_00001" : { + "minimal_similarity" : 0.3026315789473684, + "maximum_similarity" : 0.5287356321839081, + "matched_token_number" : 46 + }, + "00113_00002-00153_00001" : { + "minimal_similarity" : 0.943089430894309, + "maximum_similarity" : 0.9508196721311475, + "matched_token_number" : 116 + }, + "00044_00002-00142_00001" : { + "minimal_similarity" : 0.3813559322033898, + "maximum_similarity" : 0.45454545454545453, + "matched_token_number" : 45 + }, + "00133_00001-00196_00001" : { + "minimal_similarity" : 0.17034700315457413, + "maximum_similarity" : 0.43902439024390244, + "matched_token_number" : 54 + }, + "00097_00002-00135_00001" : { + "minimal_similarity" : 0.4041095890410959, + "maximum_similarity" : 0.5566037735849056, + "matched_token_number" : 59 + }, + "00136_00002-00154_00002" : { + "minimal_similarity" : 0.38333333333333336, + "maximum_similarity" : 0.5798319327731093, + "matched_token_number" : 69 + }, + "00031_00003-00155_00001" : { + "minimal_similarity" : 0.5287356321839081, + "maximum_similarity" : 0.5411764705882353, + "matched_token_number" : 46 + }, + "00140_00001-00204_00001" : { + "minimal_similarity" : 0.4583333333333333, + "maximum_similarity" : 0.632183908045977, + "matched_token_number" : 55 + }, + "00127_00002-00134_00001" : { + "minimal_similarity" : 0.4715447154471545, + "maximum_similarity" : 0.7160493827160493, + "matched_token_number" : 58 + }, + "00127_00002-00186_00002" : { + "minimal_similarity" : 0.4782608695652174, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00125_00001-00155_00001" : { + "minimal_similarity" : 0.5447154471544715, + "maximum_similarity" : 0.7701149425287356, + "matched_token_number" : 67 + }, + "00005_00002-00202_00003" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.5957446808510638, + "matched_token_number" : 84 + }, + "00005_00002-00202_00002" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.5957446808510638, + "matched_token_number" : 84 + }, + "00126_00002-00147_00001" : { + "minimal_similarity" : 0.5338983050847458, + "maximum_similarity" : 0.5338983050847458, + "matched_token_number" : 63 + }, + "00135_00001-00160_00001" : { + "minimal_similarity" : 0.541095890410959, + "maximum_similarity" : 0.5808823529411765, + "matched_token_number" : 79 + }, + "00014_00001-00125_00001" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00133_00001-00202_00003" : { + "minimal_similarity" : 0.4326241134751773, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00133_00001-00202_00002" : { + "minimal_similarity" : 0.46808510638297873, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00140_00001-00145_00001" : { + "minimal_similarity" : 0.5609756097560976, + "maximum_similarity" : 0.7931034482758621, + "matched_token_number" : 69 + }, + "00097_00002-00111_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5754716981132075, + "matched_token_number" : 61 + }, + "00154_00002-00192_00002" : { + "minimal_similarity" : 0.48854961832061067, + "maximum_similarity" : 0.5378151260504201, + "matched_token_number" : 64 + }, + "00097_00002-00186_00004" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.5, + "matched_token_number" : 53 + }, + "00154_00002-00192_00001" : { + "minimal_similarity" : 0.41935483870967744, + "maximum_similarity" : 0.5462184873949579, + "matched_token_number" : 65 + }, + "00137_00002-00156_00002" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00137_00002-00156_00003" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00097_00002-00186_00002" : { + "minimal_similarity" : 0.2826086956521739, + "maximum_similarity" : 0.36792452830188677, + "matched_token_number" : 39 + }, + "00000_00003-00204_00001" : { + "minimal_similarity" : 0.43333333333333335, + "maximum_similarity" : 0.4369747899159664, + "matched_token_number" : 52 + }, + "00113_00002-00155_00001" : { + "minimal_similarity" : 0.5491803278688525, + "maximum_similarity" : 0.7701149425287356, + "matched_token_number" : 67 + }, + "00000_00001-00204_00001" : { + "minimal_similarity" : 0.45, + "maximum_similarity" : 0.5510204081632653, + "matched_token_number" : 54 + }, + "00155_00001-00184_00003" : { + "minimal_similarity" : 0.5212765957446809, + "maximum_similarity" : 0.5632183908045977, + "matched_token_number" : 49 + }, + "00095_00003-00156_00003" : { + "minimal_similarity" : 0.3372093023255814, + "maximum_similarity" : 0.4264705882352941, + "matched_token_number" : 58 + }, + "00155_00001-00184_00002" : { + "minimal_similarity" : 0.5212765957446809, + "maximum_similarity" : 0.5632183908045977, + "matched_token_number" : 49 + }, + "00095_00003-00156_00002" : { + "minimal_similarity" : 0.3372093023255814, + "maximum_similarity" : 0.4264705882352941, + "matched_token_number" : 58 + }, + "00121_00001-00135_00001" : { + "minimal_similarity" : 0.541095890410959, + "maximum_similarity" : 0.5808823529411765, + "matched_token_number" : 79 + }, + "00130_00002-00199_00001" : { + "minimal_similarity" : 0.45263157894736844, + "maximum_similarity" : 0.4942528735632184, + "matched_token_number" : 43 + }, + "00134_00001-00145_00001" : { + "minimal_similarity" : 0.4715447154471545, + "maximum_similarity" : 0.7160493827160493, + "matched_token_number" : 58 + }, + "00005_00002-00200_00002" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6511627906976745, + "matched_token_number" : 84 + }, + "00156_00002-00199_00001" : { + "minimal_similarity" : 0.38235294117647056, + "maximum_similarity" : 0.5473684210526316, + "matched_token_number" : 52 + }, + "00134_00001-00198_00001" : { + "minimal_similarity" : 0.3092105263157895, + "maximum_similarity" : 0.5802469135802469, + "matched_token_number" : 47 + }, + "00135_00001-00192_00001" : { + "minimal_similarity" : 0.44516129032258067, + "maximum_similarity" : 0.4726027397260274, + "matched_token_number" : 69 + }, + "00134_00001-00203_00002" : { + "minimal_similarity" : 0.3795620437956204, + "maximum_similarity" : 0.6419753086419753, + "matched_token_number" : 52 + }, + "00135_00001-00192_00002" : { + "minimal_similarity" : 0.4041095890410959, + "maximum_similarity" : 0.45038167938931295, + "matched_token_number" : 59 + }, + "00153_00001-00187_00001" : { + "minimal_similarity" : 0.5909090909090909, + "maximum_similarity" : 0.6341463414634146, + "matched_token_number" : 78 + }, + "00140_00001-00177_00003" : { + "minimal_similarity" : 0.5609756097560976, + "maximum_similarity" : 0.7931034482758621, + "matched_token_number" : 69 + }, + "00031_00002-00130_00002" : { + "minimal_similarity" : 0.5543478260869565, + "maximum_similarity" : 0.5862068965517241, + "matched_token_number" : 51 + }, + "00013_00002-00204_00001" : { + "minimal_similarity" : 0.45, + "maximum_similarity" : 0.5684210526315789, + "matched_token_number" : 54 + }, + "00000_00001-00000_00002" : { + "minimal_similarity" : 0.782608695652174, + "maximum_similarity" : 0.9183673469387755, + "matched_token_number" : 90 + }, + "00000_00001-00000_00003" : { + "minimal_similarity" : 0.7142857142857143, + "maximum_similarity" : 0.8673469387755102, + "matched_token_number" : 85 + }, + "00031_00002-00183_00004" : { + "minimal_similarity" : 0.3546099290780142, + "maximum_similarity" : 0.5434782608695652, + "matched_token_number" : 50 + }, + "00000_00001-00000_00005" : { + "minimal_similarity" : 0.6833333333333333, + "maximum_similarity" : 0.8367346938775511, + "matched_token_number" : 82 + }, + "00184_00003-00204_00001" : { + "minimal_similarity" : 0.5416666666666666, + "maximum_similarity" : 0.6914893617021277, + "matched_token_number" : 65 + }, + "00145_00001-00183_00004" : { + "minimal_similarity" : 0.48226950354609927, + "maximum_similarity" : 0.5528455284552846, + "matched_token_number" : 68 + }, + "00000_00003-00129_00008" : { + "minimal_similarity" : 0.2680851063829787, + "maximum_similarity" : 0.5294117647058824, + "matched_token_number" : 63 + }, + "00135_00001-00198_00001" : { + "minimal_similarity" : 0.46710526315789475, + "maximum_similarity" : 0.4863013698630137, + "matched_token_number" : 71 + }, + "00044_00002-00140_00001" : { + "minimal_similarity" : 0.46464646464646464, + "maximum_similarity" : 0.5287356321839081, + "matched_token_number" : 46 + }, + "00000_00002-00156_00003" : { + "minimal_similarity" : 0.3235294117647059, + "maximum_similarity" : 0.3826086956521739, + "matched_token_number" : 44 + }, + "00044_00002-00178_00002" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.5656565656565656, + "matched_token_number" : 56 + }, + "00000_00002-00156_00002" : { + "minimal_similarity" : 0.3235294117647059, + "maximum_similarity" : 0.3826086956521739, + "matched_token_number" : 44 + }, + "00014_00001-00120_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 56 + }, + "00120_00001-00135_00001" : { + "minimal_similarity" : 0.4178082191780822, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00005_00002-00195_00002" : { + "minimal_similarity" : 0.46875, + "maximum_similarity" : 0.635593220338983, + "matched_token_number" : 75 + }, + "00005_00002-00195_00001" : { + "minimal_similarity" : 0.46875, + "maximum_similarity" : 0.635593220338983, + "matched_token_number" : 75 + }, + "00155_00001-00186_00004" : { + "minimal_similarity" : 0.44339622641509435, + "maximum_similarity" : 0.5402298850574713, + "matched_token_number" : 47 + }, + "00013_00002-00194_00001" : { + "minimal_similarity" : 0.5185185185185185, + "maximum_similarity" : 0.5894736842105263, + "matched_token_number" : 56 + }, + "00155_00001-00186_00002" : { + "minimal_similarity" : 0.35507246376811596, + "maximum_similarity" : 0.5632183908045977, + "matched_token_number" : 49 + }, + "00156_00002-00204_00001" : { + "minimal_similarity" : 0.4852941176470588, + "maximum_similarity" : 0.55, + "matched_token_number" : 66 + }, + "00044_00002-00126_00002" : { + "minimal_similarity" : 0.3813559322033898, + "maximum_similarity" : 0.45454545454545453, + "matched_token_number" : 45 + }, + "00000_00003-00202_00002" : { + "minimal_similarity" : 0.3900709219858156, + "maximum_similarity" : 0.46218487394957986, + "matched_token_number" : 55 + }, + "00177_00003-00195_00002" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00000_00003-00202_00003" : { + "minimal_similarity" : 0.3617021276595745, + "maximum_similarity" : 0.42857142857142855, + "matched_token_number" : 51 + }, + "00177_00003-00195_00001" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00131_00005-00160_00001" : { + "minimal_similarity" : 0.4125, + "maximum_similarity" : 0.4852941176470588, + "matched_token_number" : 66 + }, + "00097_00002-00119_00001" : { + "minimal_similarity" : 0.5833333333333334, + "maximum_similarity" : 0.5943396226415094, + "matched_token_number" : 63 + }, + "00156_00003-00186_00004" : { + "minimal_similarity" : 0.4411764705882353, + "maximum_similarity" : 0.5660377358490566, + "matched_token_number" : 60 + }, + "00077_00001-00184_00002" : { + "minimal_similarity" : 0.4125, + "maximum_similarity" : 0.7021276595744681, + "matched_token_number" : 66 + }, + "00095_00003-00186_00004" : { + "minimal_similarity" : 0.3081395348837209, + "maximum_similarity" : 0.5, + "matched_token_number" : 53 + }, + "00156_00003-00186_00002" : { + "minimal_similarity" : 0.37681159420289856, + "maximum_similarity" : 0.38235294117647056, + "matched_token_number" : 52 + }, + "00077_00001-00184_00003" : { + "minimal_similarity" : 0.4125, + "maximum_similarity" : 0.7021276595744681, + "matched_token_number" : 66 + }, + "00095_00003-00186_00002" : { + "minimal_similarity" : 0.3081395348837209, + "maximum_similarity" : 0.38405797101449274, + "matched_token_number" : 53 + }, + "00130_00002-00194_00001" : { + "minimal_similarity" : 0.46296296296296297, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00136_00002-00138_00001" : { + "minimal_similarity" : 0.4111111111111111, + "maximum_similarity" : 0.6271186440677966, + "matched_token_number" : 74 + }, + "00013_00002-00193_00001" : { + "minimal_similarity" : 0.5037593984962406, + "maximum_similarity" : 0.7052631578947368, + "matched_token_number" : 67 + }, + "00130_00002-00141_00002" : { + "minimal_similarity" : 0.46296296296296297, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00136_00002-00184_00003" : { + "minimal_similarity" : 0.3111111111111111, + "maximum_similarity" : 0.5957446808510638, + "matched_token_number" : 56 + }, + "00136_00002-00184_00002" : { + "minimal_similarity" : 0.3111111111111111, + "maximum_similarity" : 0.5957446808510638, + "matched_token_number" : 56 + }, + "00142_00001-00202_00003" : { + "minimal_similarity" : 0.41843971631205673, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00140_00001-00201_00001" : { + "minimal_similarity" : 0.41379310344827586, + "maximum_similarity" : 0.41379310344827586, + "matched_token_number" : 36 + }, + "00142_00001-00202_00002" : { + "minimal_similarity" : 0.4326241134751773, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00013_00002-00140_00001" : { + "minimal_similarity" : 0.47368421052631576, + "maximum_similarity" : 0.5172413793103449, + "matched_token_number" : 45 + }, + "00119_00001-00127_00002" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00005_00002-00031_00003" : { + "minimal_similarity" : 0.3375, + "maximum_similarity" : 0.6352941176470588, + "matched_token_number" : 54 + }, + "00000_00001-00005_00002" : { + "minimal_similarity" : 0.3875, + "maximum_similarity" : 0.6326530612244898, + "matched_token_number" : 62 + }, + "00005_00002-00031_00002" : { + "minimal_similarity" : 0.35, + "maximum_similarity" : 0.6086956521739131, + "matched_token_number" : 56 + }, + "00135_00001-00193_00001" : { + "minimal_similarity" : 0.4520547945205479, + "maximum_similarity" : 0.49624060150375937, + "matched_token_number" : 66 + }, + "00184_00003-00194_00001" : { + "minimal_similarity" : 0.5092592592592593, + "maximum_similarity" : 0.5851063829787234, + "matched_token_number" : 55 + }, + "00177_00003-00194_00001" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00031_00002-00135_00001" : { + "minimal_similarity" : 0.4520547945205479, + "maximum_similarity" : 0.717391304347826, + "matched_token_number" : 66 + }, + "00095_00003-00153_00001" : { + "minimal_similarity" : 0.42441860465116277, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00077_00001-00138_00001" : { + "minimal_similarity" : 0.45625, + "maximum_similarity" : 0.6186440677966102, + "matched_token_number" : 73 + }, + "00120_00001-00130_00002" : { + "minimal_similarity" : 0.4406779661016949, + "maximum_similarity" : 0.5977011494252874, + "matched_token_number" : 52 + }, + "00133_00001-00140_00001" : { + "minimal_similarity" : 0.5609756097560976, + "maximum_similarity" : 0.7931034482758621, + "matched_token_number" : 69 + }, + "00077_00001-00131_00005" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 160 + }, + "00092_00001-00155_00001" : { + "minimal_similarity" : 0.3220338983050847, + "maximum_similarity" : 0.4367816091954023, + "matched_token_number" : 38 + }, + "00013_00002-00199_00001" : { + "minimal_similarity" : 0.4842105263157895, + "maximum_similarity" : 0.4842105263157895, + "matched_token_number" : 46 + }, + "00121_00001-00134_00001" : { + "minimal_similarity" : 0.3602941176470588, + "maximum_similarity" : 0.6049382716049383, + "matched_token_number" : 49 + }, + "00044_00002-00121_00001" : { + "minimal_similarity" : 0.47058823529411764, + "maximum_similarity" : 0.6464646464646465, + "matched_token_number" : 64 + }, + "00177_00003-00200_00002" : { + "minimal_similarity" : 0.5658914728682171, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00129_00008-00154_00002" : { + "minimal_similarity" : 0.3276595744680851, + "maximum_similarity" : 0.6470588235294118, + "matched_token_number" : 77 + }, + "00013_00002-00147_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5894736842105263, + "matched_token_number" : 56 + }, + "00000_00002-00137_00002" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.48695652173913045, + "matched_token_number" : 56 + }, + "00136_00002-00186_00004" : { + "minimal_similarity" : 0.4111111111111111, + "maximum_similarity" : 0.6981132075471698, + "matched_token_number" : 74 + }, + "00044_00002-00177_00003" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.5656565656565656, + "matched_token_number" : 56 + }, + "00142_00001-00195_00001" : { + "minimal_similarity" : 0.9830508474576272, + "maximum_similarity" : 0.9830508474576272, + "matched_token_number" : 116 + }, + "00136_00002-00186_00002" : { + "minimal_similarity" : 0.4777777777777778, + "maximum_similarity" : 0.6231884057971014, + "matched_token_number" : 86 + }, + "00142_00001-00195_00002" : { + "minimal_similarity" : 0.9830508474576272, + "maximum_similarity" : 0.9830508474576272, + "matched_token_number" : 116 + }, + "00120_00001-00184_00002" : { + "minimal_similarity" : 0.4661016949152542, + "maximum_similarity" : 0.5851063829787234, + "matched_token_number" : 55 + }, + "00013_00002-00145_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.6421052631578947, + "matched_token_number" : 61 + }, + "00120_00001-00184_00003" : { + "minimal_similarity" : 0.4661016949152542, + "maximum_similarity" : 0.5851063829787234, + "matched_token_number" : 55 + }, + "00160_00001-00184_00003" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.723404255319149, + "matched_token_number" : 68 + }, + "00160_00001-00184_00002" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.723404255319149, + "matched_token_number" : 68 + }, + "00137_00002-00153_00001" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00013_00002-00198_00001" : { + "minimal_similarity" : 0.3684210526315789, + "maximum_similarity" : 0.5894736842105263, + "matched_token_number" : 56 + }, + "00186_00004-00187_00001" : { + "minimal_similarity" : 0.5075757575757576, + "maximum_similarity" : 0.6320754716981132, + "matched_token_number" : 67 + }, + "00044_00002-00127_00002" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.5656565656565656, + "matched_token_number" : 56 + }, + "00000_00003-00178_00002" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.47058823529411764, + "matched_token_number" : 56 + }, + "00005_00002-00141_00002" : { + "minimal_similarity" : 0.3375, + "maximum_similarity" : 0.5, + "matched_token_number" : 54 + }, + "00111_00001-00113_00002" : { + "minimal_similarity" : 0.943089430894309, + "maximum_similarity" : 0.9508196721311475, + "matched_token_number" : 116 + }, + "00000_00002-00138_00001" : { + "minimal_similarity" : 0.4322033898305085, + "maximum_similarity" : 0.4434782608695652, + "matched_token_number" : 51 + }, + "00160_00001-00187_00001" : { + "minimal_similarity" : 0.625, + "maximum_similarity" : 0.6439393939393939, + "matched_token_number" : 85 + }, + "00200_00002-00203_00002" : { + "minimal_similarity" : 0.5109489051094891, + "maximum_similarity" : 0.5426356589147286, + "matched_token_number" : 70 + }, + "00092_00001-00153_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00142_00001-00203_00002" : { + "minimal_similarity" : 0.45255474452554745, + "maximum_similarity" : 0.5254237288135594, + "matched_token_number" : 62 + }, + "00077_00001-00133_00001" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00130_00002-00195_00002" : { + "minimal_similarity" : 0.4406779661016949, + "maximum_similarity" : 0.5977011494252874, + "matched_token_number" : 52 + }, + "00130_00002-00195_00001" : { + "minimal_similarity" : 0.4406779661016949, + "maximum_similarity" : 0.5977011494252874, + "matched_token_number" : 52 + }, + "00031_00002-00184_00002" : { + "minimal_similarity" : 0.48936170212765956, + "maximum_similarity" : 0.5, + "matched_token_number" : 46 + }, + "00077_00001-00136_00002" : { + "minimal_similarity" : 0.4722222222222222, + "maximum_similarity" : 0.53125, + "matched_token_number" : 85 + }, + "00031_00002-00184_00003" : { + "minimal_similarity" : 0.48936170212765956, + "maximum_similarity" : 0.5, + "matched_token_number" : 46 + }, + "00147_00001-00187_00001" : { + "minimal_similarity" : 0.48484848484848486, + "maximum_similarity" : 0.5423728813559322, + "matched_token_number" : 64 + }, + "00184_00003-00200_00002" : { + "minimal_similarity" : 0.4186046511627907, + "maximum_similarity" : 0.574468085106383, + "matched_token_number" : 54 + }, + "00000_00003-00192_00002" : { + "minimal_similarity" : 0.44274809160305345, + "maximum_similarity" : 0.48739495798319327, + "matched_token_number" : 58 + }, + "00140_00001-00178_00002" : { + "minimal_similarity" : 0.5609756097560976, + "maximum_similarity" : 0.7931034482758621, + "matched_token_number" : 69 + }, + "00000_00003-00192_00001" : { + "minimal_similarity" : 0.36129032258064514, + "maximum_similarity" : 0.47058823529411764, + "matched_token_number" : 56 + }, + "00000_00005-00155_00001" : { + "minimal_similarity" : 0.36666666666666664, + "maximum_similarity" : 0.5057471264367817, + "matched_token_number" : 44 + }, + "00013_00002-00142_00001" : { + "minimal_similarity" : 0.4067796610169492, + "maximum_similarity" : 0.5052631578947369, + "matched_token_number" : 48 + }, + "00135_00001-00197_00001" : { + "minimal_similarity" : 0.4931506849315068, + "maximum_similarity" : 0.5454545454545454, + "matched_token_number" : 72 + }, + "00134_00001-00193_00001" : { + "minimal_similarity" : 0.3684210526315789, + "maximum_similarity" : 0.6049382716049383, + "matched_token_number" : 49 + }, + "00120_00001-00186_00004" : { + "minimal_similarity" : 0.423728813559322, + "maximum_similarity" : 0.4716981132075472, + "matched_token_number" : 50 + }, + "00000_00003-00127_00002" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.47058823529411764, + "matched_token_number" : 56 + }, + "00142_00001-00197_00001" : { + "minimal_similarity" : 0.4393939393939394, + "maximum_similarity" : 0.4915254237288136, + "matched_token_number" : 58 + }, + "00000_00003-00140_00001" : { + "minimal_similarity" : 0.4369747899159664, + "maximum_similarity" : 0.5977011494252874, + "matched_token_number" : 52 + }, + "00120_00001-00186_00002" : { + "minimal_similarity" : 0.3695652173913043, + "maximum_similarity" : 0.4322033898305085, + "matched_token_number" : 51 + }, + "00134_00001-00140_00001" : { + "minimal_similarity" : 0.632183908045977, + "maximum_similarity" : 0.6790123456790124, + "matched_token_number" : 55 + }, + "00156_00002-00194_00001" : { + "minimal_similarity" : 0.5220588235294118, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00005_00002-00127_00002" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00077_00001-00135_00001" : { + "minimal_similarity" : 0.45625, + "maximum_similarity" : 0.5, + "matched_token_number" : 73 + }, + "00130_00002-00202_00002" : { + "minimal_similarity" : 0.40425531914893614, + "maximum_similarity" : 0.6551724137931034, + "matched_token_number" : 57 + }, + "00135_00001-00203_00002" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.5328467153284672, + "matched_token_number" : 73 + }, + "00136_00002-00187_00001" : { + "minimal_similarity" : 0.42777777777777776, + "maximum_similarity" : 0.5833333333333334, + "matched_token_number" : 77 + }, + "00130_00002-00197_00001" : { + "minimal_similarity" : 0.44696969696969696, + "maximum_similarity" : 0.6781609195402298, + "matched_token_number" : 59 + }, + "00013_00002-00196_00001" : { + "minimal_similarity" : 0.15772870662460567, + "maximum_similarity" : 0.5263157894736842, + "matched_token_number" : 50 + }, + "00130_00002-00202_00003" : { + "minimal_similarity" : 0.40425531914893614, + "maximum_similarity" : 0.6551724137931034, + "matched_token_number" : 57 + }, + "00156_00002-00193_00001" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.5112781954887218, + "matched_token_number" : 68 + }, + "00113_00002-00120_00001" : { + "minimal_similarity" : 0.5737704918032787, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00184_00003-00192_00002" : { + "minimal_similarity" : 0.5343511450381679, + "maximum_similarity" : 0.7446808510638298, + "matched_token_number" : 70 + }, + "00184_00003-00192_00001" : { + "minimal_similarity" : 0.432258064516129, + "maximum_similarity" : 0.7127659574468085, + "matched_token_number" : 67 + }, + "00133_00001-00178_00002" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00120_00001-00133_00001" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00000_00002-00092_00001" : { + "minimal_similarity" : 0.4322033898305085, + "maximum_similarity" : 0.4434782608695652, + "matched_token_number" : 51 + }, + "00121_00001-00137_00002" : { + "minimal_similarity" : 0.6985294117647058, + "maximum_similarity" : 0.7723577235772358, + "matched_token_number" : 95 + }, + "00153_00001-00183_00004" : { + "minimal_similarity" : 0.48226950354609927, + "maximum_similarity" : 0.5528455284552846, + "matched_token_number" : 68 + }, + "00203_00002-00204_00001" : { + "minimal_similarity" : 0.6131386861313869, + "maximum_similarity" : 0.7, + "matched_token_number" : 84 + }, + "00121_00001-00198_00001" : { + "minimal_similarity" : 0.4473684210526316, + "maximum_similarity" : 0.5, + "matched_token_number" : 68 + }, + "00140_00001-00194_00001" : { + "minimal_similarity" : 0.46296296296296297, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00077_00001-00127_00002" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00184_00003-00196_00001" : { + "minimal_similarity" : 0.1608832807570978, + "maximum_similarity" : 0.5425531914893617, + "matched_token_number" : 51 + }, + "00135_00001-00142_00001" : { + "minimal_similarity" : 0.4178082191780822, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00000_00005-00141_00002" : { + "minimal_similarity" : 0.4666666666666667, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 56 + }, + "00031_00002-00120_00001" : { + "minimal_similarity" : 0.4322033898305085, + "maximum_similarity" : 0.5543478260869565, + "matched_token_number" : 51 + }, + "00031_00003-00095_00003" : { + "minimal_similarity" : 0.27325581395348836, + "maximum_similarity" : 0.5529411764705883, + "matched_token_number" : 47 + }, + "00031_00002-00095_00003" : { + "minimal_similarity" : 0.3023255813953488, + "maximum_similarity" : 0.5652173913043478, + "matched_token_number" : 52 + }, + "00044_00002-00130_00002" : { + "minimal_similarity" : 0.46464646464646464, + "maximum_similarity" : 0.5287356321839081, + "matched_token_number" : 46 + }, + "00136_00002-00195_00002" : { + "minimal_similarity" : 0.2722222222222222, + "maximum_similarity" : 0.4152542372881356, + "matched_token_number" : 49 + }, + "00113_00002-00119_00001" : { + "minimal_similarity" : 0.5819672131147541, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00136_00002-00195_00001" : { + "minimal_similarity" : 0.2722222222222222, + "maximum_similarity" : 0.4152542372881356, + "matched_token_number" : 49 + }, + "00126_00002-00129_00008" : { + "minimal_similarity" : 0.2723404255319149, + "maximum_similarity" : 0.5423728813559322, + "matched_token_number" : 64 + }, + "00000_00002-00141_00002" : { + "minimal_similarity" : 0.4782608695652174, + "maximum_similarity" : 0.5092592592592593, + "matched_token_number" : 55 + }, + "00201_00001-00204_00001" : { + "minimal_similarity" : 0.2833333333333333, + "maximum_similarity" : 0.39080459770114945, + "matched_token_number" : 34 + }, + "00178_00002-00184_00003" : { + "minimal_similarity" : 0.5203252032520326, + "maximum_similarity" : 0.6808510638297872, + "matched_token_number" : 64 + }, + "00178_00002-00184_00002" : { + "minimal_similarity" : 0.5203252032520326, + "maximum_similarity" : 0.6808510638297872, + "matched_token_number" : 64 + }, + "00111_00001-00127_00002" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00137_00002-00155_00001" : { + "minimal_similarity" : 0.5447154471544715, + "maximum_similarity" : 0.7701149425287356, + "matched_token_number" : 67 + }, + "00142_00001-00199_00001" : { + "minimal_similarity" : 0.4830508474576271, + "maximum_similarity" : 0.6, + "matched_token_number" : 57 + }, + "00014_00001-00129_00008" : { + "minimal_similarity" : 0.2978723404255319, + "maximum_similarity" : 0.6481481481481481, + "matched_token_number" : 70 + }, + "00095_00003-00201_00001" : { + "minimal_similarity" : 0.25, + "maximum_similarity" : 0.4942528735632184, + "matched_token_number" : 43 + }, + "00113_00002-00186_00004" : { + "minimal_similarity" : 0.45901639344262296, + "maximum_similarity" : 0.5283018867924528, + "matched_token_number" : 56 + }, + "00140_00001-00199_00001" : { + "minimal_similarity" : 0.45263157894736844, + "maximum_similarity" : 0.4942528735632184, + "matched_token_number" : 43 + }, + "00177_00003-00178_00002" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00138_00001-00204_00001" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.5084745762711864, + "matched_token_number" : 60 + }, + "00000_00001-00095_00003" : { + "minimal_similarity" : 0.313953488372093, + "maximum_similarity" : 0.5510204081632653, + "matched_token_number" : 54 + }, + "00126_00002-00196_00001" : { + "minimal_similarity" : 0.17981072555205047, + "maximum_similarity" : 0.4830508474576271, + "matched_token_number" : 57 + }, + "00097_00002-00155_00001" : { + "minimal_similarity" : 0.5283018867924528, + "maximum_similarity" : 0.6436781609195402, + "matched_token_number" : 56 + }, + "00000_00001-00120_00001" : { + "minimal_similarity" : 0.4406779661016949, + "maximum_similarity" : 0.5306122448979592, + "matched_token_number" : 52 + }, + "00113_00002-00186_00002" : { + "minimal_similarity" : 0.4782608695652174, + "maximum_similarity" : 0.5409836065573771, + "matched_token_number" : 66 + }, + "00031_00002-00192_00002" : { + "minimal_similarity" : 0.4351145038167939, + "maximum_similarity" : 0.6195652173913043, + "matched_token_number" : 57 + }, + "00160_00001-00201_00001" : { + "minimal_similarity" : 0.3161764705882353, + "maximum_similarity" : 0.4942528735632184, + "matched_token_number" : 43 + }, + "00031_00002-00192_00001" : { + "minimal_similarity" : 0.3225806451612903, + "maximum_similarity" : 0.5434782608695652, + "matched_token_number" : 50 + }, + "00077_00001-00097_00002" : { + "minimal_similarity" : 0.3, + "maximum_similarity" : 0.4528301886792453, + "matched_token_number" : 48 + }, + "00131_00005-00184_00002" : { + "minimal_similarity" : 0.4125, + "maximum_similarity" : 0.7021276595744681, + "matched_token_number" : 66 + }, + "00131_00005-00184_00003" : { + "minimal_similarity" : 0.4125, + "maximum_similarity" : 0.7021276595744681, + "matched_token_number" : 66 + }, + "00192_00001-00195_00002" : { + "minimal_similarity" : 0.4129032258064516, + "maximum_similarity" : 0.5423728813559322, + "matched_token_number" : 64 + }, + "00192_00001-00195_00001" : { + "minimal_similarity" : 0.4129032258064516, + "maximum_similarity" : 0.5423728813559322, + "matched_token_number" : 64 + }, + "00142_00001-00160_00001" : { + "minimal_similarity" : 0.47058823529411764, + "maximum_similarity" : 0.5423728813559322, + "matched_token_number" : 64 + }, + "00000_00005-00154_00002" : { + "minimal_similarity" : 0.4666666666666667, + "maximum_similarity" : 0.47058823529411764, + "matched_token_number" : 56 + }, + "00129_00008-00130_00002" : { + "minimal_similarity" : 0.20425531914893616, + "maximum_similarity" : 0.5517241379310345, + "matched_token_number" : 48 + }, + "00131_00005-00197_00001" : { + "minimal_similarity" : 0.49375, + "maximum_similarity" : 0.5984848484848485, + "matched_token_number" : 79 + }, + "00005_00002-00119_00001" : { + "minimal_similarity" : 0.3375, + "maximum_similarity" : 0.5, + "matched_token_number" : 54 + }, + "00186_00004-00196_00001" : { + "minimal_similarity" : 0.11041009463722397, + "maximum_similarity" : 0.330188679245283, + "matched_token_number" : 35 + }, + "00000_00001-00154_00002" : { + "minimal_similarity" : 0.453781512605042, + "maximum_similarity" : 0.5510204081632653, + "matched_token_number" : 54 + }, + "00000_00003-00044_00002" : { + "minimal_similarity" : 0.46218487394957986, + "maximum_similarity" : 0.5555555555555556, + "matched_token_number" : 55 + }, + "00119_00001-00160_00001" : { + "minimal_similarity" : 0.6029411764705882, + "maximum_similarity" : 0.7592592592592593, + "matched_token_number" : 82 + }, + "00119_00001-00131_00005" : { + "minimal_similarity" : 0.3375, + "maximum_similarity" : 0.5, + "matched_token_number" : 54 + }, + "00120_00001-00153_00001" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00092_00001-00131_00005" : { + "minimal_similarity" : 0.45625, + "maximum_similarity" : 0.6186440677966102, + "matched_token_number" : 73 + }, + "00134_00001-00195_00002" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.691358024691358, + "matched_token_number" : 56 + }, + "00000_00002-00044_00002" : { + "minimal_similarity" : 0.48695652173913045, + "maximum_similarity" : 0.5656565656565656, + "matched_token_number" : 56 + }, + "00014_00001-00196_00001" : { + "minimal_similarity" : 0.17034700315457413, + "maximum_similarity" : 0.5, + "matched_token_number" : 54 + }, + "00134_00001-00195_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.691358024691358, + "matched_token_number" : 56 + }, + "00077_00001-00194_00001" : { + "minimal_similarity" : 0.3375, + "maximum_similarity" : 0.5, + "matched_token_number" : 54 + }, + "00000_00005-00095_00003" : { + "minimal_similarity" : 0.3081395348837209, + "maximum_similarity" : 0.44166666666666665, + "matched_token_number" : 53 + }, + "00194_00001-00195_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 56 + }, + "00000_00005-00200_00002" : { + "minimal_similarity" : 0.4806201550387597, + "maximum_similarity" : 0.5166666666666667, + "matched_token_number" : 62 + }, + "00194_00001-00195_00002" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 56 + }, + "00137_00002-00193_00001" : { + "minimal_similarity" : 0.5488721804511278, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00000_00002-00200_00002" : { + "minimal_similarity" : 0.46511627906976744, + "maximum_similarity" : 0.5217391304347826, + "matched_token_number" : 60 + }, + "00077_00001-00092_00001" : { + "minimal_similarity" : 0.45625, + "maximum_similarity" : 0.6186440677966102, + "matched_token_number" : 73 + }, + "00000_00001-00125_00001" : { + "minimal_similarity" : 0.43902439024390244, + "maximum_similarity" : 0.5510204081632653, + "matched_token_number" : 54 + }, + "00111_00001-00160_00001" : { + "minimal_similarity" : 0.6102941176470589, + "maximum_similarity" : 0.6747967479674797, + "matched_token_number" : 83 + }, + "00014_00001-00044_00002" : { + "minimal_similarity" : 0.4537037037037037, + "maximum_similarity" : 0.494949494949495, + "matched_token_number" : 49 + }, + "00031_00002-00197_00001" : { + "minimal_similarity" : 0.4090909090909091, + "maximum_similarity" : 0.5869565217391305, + "matched_token_number" : 54 + }, + "00119_00001-00194_00001" : { + "minimal_similarity" : 0.9722222222222222, + "maximum_similarity" : 0.9722222222222222, + "matched_token_number" : 105 + }, + "00133_00001-00197_00001" : { + "minimal_similarity" : 0.5909090909090909, + "maximum_similarity" : 0.6341463414634146, + "matched_token_number" : 78 + }, + "00177_00003-00199_00001" : { + "minimal_similarity" : 0.5121951219512195, + "maximum_similarity" : 0.6631578947368421, + "matched_token_number" : 63 + }, + "00000_00003-00138_00001" : { + "minimal_similarity" : 0.40336134453781514, + "maximum_similarity" : 0.4067796610169492, + "matched_token_number" : 48 + }, + "00187_00001-00194_00001" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.6111111111111112, + "matched_token_number" : 66 + }, + "00142_00001-00178_00002" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00111_00001-00156_00002" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00077_00001-00130_00002" : { + "minimal_similarity" : 0.3375, + "maximum_similarity" : 0.6206896551724138, + "matched_token_number" : 54 + }, + "00111_00001-00156_00003" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00125_00001-00130_00002" : { + "minimal_similarity" : 0.5609756097560976, + "maximum_similarity" : 0.7931034482758621, + "matched_token_number" : 69 + }, + "00111_00001-00199_00001" : { + "minimal_similarity" : 0.5121951219512195, + "maximum_similarity" : 0.6631578947368421, + "matched_token_number" : 63 + }, + "00141_00002-00192_00001" : { + "minimal_similarity" : 0.41935483870967744, + "maximum_similarity" : 0.6018518518518519, + "matched_token_number" : 65 + }, + "00141_00002-00192_00002" : { + "minimal_similarity" : 0.5190839694656488, + "maximum_similarity" : 0.6296296296296297, + "matched_token_number" : 68 + }, + "00156_00002-00198_00001" : { + "minimal_similarity" : 0.48026315789473684, + "maximum_similarity" : 0.5367647058823529, + "matched_token_number" : 73 + }, + "00153_00001-00200_00002" : { + "minimal_similarity" : 0.5658914728682171, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00131_00005-00155_00001" : { + "minimal_similarity" : 0.3125, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00077_00001-00199_00001" : { + "minimal_similarity" : 0.41875, + "maximum_similarity" : 0.7052631578947368, + "matched_token_number" : 67 + }, + "00184_00002-00200_00002" : { + "minimal_similarity" : 0.4186046511627907, + "maximum_similarity" : 0.574468085106383, + "matched_token_number" : 54 + }, + "00097_00002-00192_00001" : { + "minimal_similarity" : 0.41935483870967744, + "maximum_similarity" : 0.6132075471698113, + "matched_token_number" : 65 + }, + "00097_00002-00192_00002" : { + "minimal_similarity" : 0.4198473282442748, + "maximum_similarity" : 0.5188679245283019, + "matched_token_number" : 55 + }, + "00119_00001-00136_00002" : { + "minimal_similarity" : 0.35555555555555557, + "maximum_similarity" : 0.5925925925925926, + "matched_token_number" : 64 + }, + "00126_00002-00183_00004" : { + "minimal_similarity" : 0.3404255319148936, + "maximum_similarity" : 0.4067796610169492, + "matched_token_number" : 48 + }, + "00097_00002-00184_00003" : { + "minimal_similarity" : 0.46226415094339623, + "maximum_similarity" : 0.5212765957446809, + "matched_token_number" : 49 + }, + "00097_00002-00184_00002" : { + "minimal_similarity" : 0.46226415094339623, + "maximum_similarity" : 0.5212765957446809, + "matched_token_number" : 49 + }, + "00031_00003-00184_00002" : { + "minimal_similarity" : 0.4574468085106383, + "maximum_similarity" : 0.5058823529411764, + "matched_token_number" : 43 + }, + "00044_00002-00194_00001" : { + "minimal_similarity" : 0.4537037037037037, + "maximum_similarity" : 0.494949494949495, + "matched_token_number" : 49 + }, + "00031_00002-00031_00003" : { + "minimal_similarity" : 0.5760869565217391, + "maximum_similarity" : 0.6235294117647059, + "matched_token_number" : 53 + }, + "00031_00003-00184_00003" : { + "minimal_similarity" : 0.4574468085106383, + "maximum_similarity" : 0.5058823529411764, + "matched_token_number" : 43 + }, + "00013_00002-00127_00002" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.6421052631578947, + "matched_token_number" : 61 + }, + "00113_00002-00156_00003" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.5, + "matched_token_number" : 61 + }, + "00113_00002-00156_00002" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.5, + "matched_token_number" : 61 + }, + "00125_00001-00126_00002" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00202_00002-00202_00003" : { + "minimal_similarity" : 0.9645390070921985, + "maximum_similarity" : 0.9645390070921985, + "matched_token_number" : 136 + }, + "00197_00001-00198_00001" : { + "minimal_similarity" : 0.5986842105263158, + "maximum_similarity" : 0.6893939393939394, + "matched_token_number" : 91 + }, + "00120_00001-00196_00001" : { + "minimal_similarity" : 0.17981072555205047, + "maximum_similarity" : 0.4830508474576271, + "matched_token_number" : 57 + }, + "00092_00001-00136_00002" : { + "minimal_similarity" : 0.4111111111111111, + "maximum_similarity" : 0.6271186440677966, + "matched_token_number" : 74 + }, + "00095_00003-00184_00003" : { + "minimal_similarity" : 0.31976744186046513, + "maximum_similarity" : 0.5851063829787234, + "matched_token_number" : 55 + }, + "00156_00003-00194_00001" : { + "minimal_similarity" : 0.5220588235294118, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00121_00001-00130_00002" : { + "minimal_similarity" : 0.4632352941176471, + "maximum_similarity" : 0.7241379310344828, + "matched_token_number" : 63 + }, + "00095_00003-00184_00002" : { + "minimal_similarity" : 0.31976744186046513, + "maximum_similarity" : 0.5851063829787234, + "matched_token_number" : 55 + }, + "00111_00001-00119_00001" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00154_00002-00193_00001" : { + "minimal_similarity" : 0.48120300751879697, + "maximum_similarity" : 0.5378151260504201, + "matched_token_number" : 64 + }, + "00000_00003-00196_00001" : { + "minimal_similarity" : 0.17350157728706625, + "maximum_similarity" : 0.46218487394957986, + "matched_token_number" : 55 + }, + "00155_00001-00183_00004" : { + "minimal_similarity" : 0.2553191489361702, + "maximum_similarity" : 0.41379310344827586, + "matched_token_number" : 36 + }, + "00000_00001-00196_00001" : { + "minimal_similarity" : 0.13564668769716087, + "maximum_similarity" : 0.4387755102040816, + "matched_token_number" : 43 + }, + "00156_00002-00177_00003" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00129_00008-00198_00001" : { + "minimal_similarity" : 0.34893617021276596, + "maximum_similarity" : 0.5394736842105263, + "matched_token_number" : 82 + }, + "00044_00002-00135_00001" : { + "minimal_similarity" : 0.3356164383561644, + "maximum_similarity" : 0.494949494949495, + "matched_token_number" : 49 + }, + "00121_00001-00126_00002" : { + "minimal_similarity" : 0.4632352941176471, + "maximum_similarity" : 0.5338983050847458, + "matched_token_number" : 63 + }, + "00013_00002-00156_00002" : { + "minimal_similarity" : 0.36764705882352944, + "maximum_similarity" : 0.5263157894736842, + "matched_token_number" : 50 + }, + "00013_00002-00156_00003" : { + "minimal_similarity" : 0.36764705882352944, + "maximum_similarity" : 0.5263157894736842, + "matched_token_number" : 50 + }, + "00156_00003-00193_00001" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.5112781954887218, + "matched_token_number" : 68 + }, + "00127_00002-00156_00002" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00127_00002-00156_00003" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00178_00002-00201_00001" : { + "minimal_similarity" : 0.3008130081300813, + "maximum_similarity" : 0.42528735632183906, + "matched_token_number" : 37 + }, + "00125_00001-00127_00002" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00000_00001-00197_00001" : { + "minimal_similarity" : 0.4090909090909091, + "maximum_similarity" : 0.5510204081632653, + "matched_token_number" : 54 + }, + "00136_00002-00153_00001" : { + "minimal_similarity" : 0.4, + "maximum_similarity" : 0.5853658536585366, + "matched_token_number" : 72 + }, + "00000_00003-00197_00001" : { + "minimal_similarity" : 0.4090909090909091, + "maximum_similarity" : 0.453781512605042, + "matched_token_number" : 54 + }, + "00113_00002-00178_00002" : { + "minimal_similarity" : 0.943089430894309, + "maximum_similarity" : 0.9508196721311475, + "matched_token_number" : 116 + }, + "00192_00002-00204_00001" : { + "minimal_similarity" : 0.6717557251908397, + "maximum_similarity" : 0.7333333333333333, + "matched_token_number" : 88 + }, + "00195_00002-00202_00002" : { + "minimal_similarity" : 0.4326241134751773, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00195_00002-00202_00003" : { + "minimal_similarity" : 0.41843971631205673, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00133_00001-00138_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00126_00002-00153_00001" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00005_00002-00203_00002" : { + "minimal_similarity" : 0.48125, + "maximum_similarity" : 0.5620437956204379, + "matched_token_number" : 77 + }, + "00013_00002-00097_00002" : { + "minimal_similarity" : 0.5188679245283019, + "maximum_similarity" : 0.5789473684210527, + "matched_token_number" : 55 + }, + "00031_00003-00154_00002" : { + "minimal_similarity" : 0.4369747899159664, + "maximum_similarity" : 0.611764705882353, + "matched_token_number" : 52 + }, + "00193_00001-00197_00001" : { + "minimal_similarity" : 0.6165413533834586, + "maximum_similarity" : 0.6212121212121212, + "matched_token_number" : 82 + }, + "00125_00001-00134_00001" : { + "minimal_similarity" : 0.4715447154471545, + "maximum_similarity" : 0.7160493827160493, + "matched_token_number" : 58 + }, + "00121_00001-00155_00001" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.7011494252873564, + "matched_token_number" : 61 + }, + "00156_00003-00199_00001" : { + "minimal_similarity" : 0.38235294117647056, + "maximum_similarity" : 0.5473684210526316, + "matched_token_number" : 52 + }, + "00187_00001-00198_00001" : { + "minimal_similarity" : 0.5986842105263158, + "maximum_similarity" : 0.6893939393939394, + "matched_token_number" : 91 + }, + "00013_00002-00119_00001" : { + "minimal_similarity" : 0.5185185185185185, + "maximum_similarity" : 0.5894736842105263, + "matched_token_number" : 56 + }, + "00000_00001-00129_00008" : { + "minimal_similarity" : 0.251063829787234, + "maximum_similarity" : 0.6020408163265306, + "matched_token_number" : 59 + }, + "00119_00001-00135_00001" : { + "minimal_similarity" : 0.4589041095890411, + "maximum_similarity" : 0.6203703703703703, + "matched_token_number" : 67 + }, + "00044_00002-00193_00001" : { + "minimal_similarity" : 0.5037593984962406, + "maximum_similarity" : 0.6767676767676768, + "matched_token_number" : 67 + }, + "00092_00001-00127_00002" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00031_00003-00183_00004" : { + "minimal_similarity" : 0.36879432624113473, + "maximum_similarity" : 0.611764705882353, + "matched_token_number" : 52 + }, + "00154_00002-00194_00001" : { + "minimal_similarity" : 0.5714285714285714, + "maximum_similarity" : 0.6296296296296297, + "matched_token_number" : 68 + }, + "00126_00002-00187_00001" : { + "minimal_similarity" : 0.4393939393939394, + "maximum_similarity" : 0.4915254237288136, + "matched_token_number" : 58 + }, + "00097_00002-00193_00001" : { + "minimal_similarity" : 0.39849624060150374, + "maximum_similarity" : 0.5, + "matched_token_number" : 53 + }, + "00129_00008-00193_00001" : { + "minimal_similarity" : 0.3446808510638298, + "maximum_similarity" : 0.6090225563909775, + "matched_token_number" : 81 + }, + "00013_00002-00126_00002" : { + "minimal_similarity" : 0.4067796610169492, + "maximum_similarity" : 0.5052631578947369, + "matched_token_number" : 48 + }, + "00044_00002-00160_00001" : { + "minimal_similarity" : 0.4264705882352941, + "maximum_similarity" : 0.5858585858585859, + "matched_token_number" : 58 + }, + "00000_00002-00184_00002" : { + "minimal_similarity" : 0.48695652173913045, + "maximum_similarity" : 0.5957446808510638, + "matched_token_number" : 56 + }, + "00031_00002-00196_00001" : { + "minimal_similarity" : 0.12618296529968454, + "maximum_similarity" : 0.43478260869565216, + "matched_token_number" : 40 + }, + "00000_00002-00184_00003" : { + "minimal_similarity" : 0.48695652173913045, + "maximum_similarity" : 0.5957446808510638, + "matched_token_number" : 56 + }, + "00127_00002-00199_00001" : { + "minimal_similarity" : 0.5121951219512195, + "maximum_similarity" : 0.6631578947368421, + "matched_token_number" : 63 + }, + "00000_00005-00184_00003" : { + "minimal_similarity" : 0.49166666666666664, + "maximum_similarity" : 0.6276595744680851, + "matched_token_number" : 59 + }, + "00000_00001-00184_00003" : { + "minimal_similarity" : 0.5102040816326531, + "maximum_similarity" : 0.5319148936170213, + "matched_token_number" : 50 + }, + "00005_00002-00097_00002" : { + "minimal_similarity" : 0.3, + "maximum_similarity" : 0.4528301886792453, + "matched_token_number" : 48 + }, + "00000_00005-00184_00002" : { + "minimal_similarity" : 0.49166666666666664, + "maximum_similarity" : 0.6276595744680851, + "matched_token_number" : 59 + }, + "00000_00001-00184_00002" : { + "minimal_similarity" : 0.5102040816326531, + "maximum_similarity" : 0.5319148936170213, + "matched_token_number" : 50 + }, + "00156_00003-00160_00001" : { + "minimal_similarity" : 0.5514705882352942, + "maximum_similarity" : 0.5514705882352942, + "matched_token_number" : 75 + }, + "00127_00002-00186_00004" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.5283018867924528, + "matched_token_number" : 56 + }, + "00145_00001-00201_00001" : { + "minimal_similarity" : 0.3008130081300813, + "maximum_similarity" : 0.42528735632183906, + "matched_token_number" : 37 + }, + "00156_00002-00160_00001" : { + "minimal_similarity" : 0.5514705882352942, + "maximum_similarity" : 0.5514705882352942, + "matched_token_number" : 75 + }, + "00183_00004-00193_00001" : { + "minimal_similarity" : 0.5886524822695035, + "maximum_similarity" : 0.6240601503759399, + "matched_token_number" : 83 + }, + "00125_00001-00194_00001" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00183_00004-00199_00001" : { + "minimal_similarity" : 0.3971631205673759, + "maximum_similarity" : 0.5894736842105263, + "matched_token_number" : 56 + }, + "00142_00001-00177_00003" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00000_00005-00183_00004" : { + "minimal_similarity" : 0.3900709219858156, + "maximum_similarity" : 0.4583333333333333, + "matched_token_number" : 55 + }, + "00129_00008-00194_00001" : { + "minimal_similarity" : 0.2978723404255319, + "maximum_similarity" : 0.6481481481481481, + "matched_token_number" : 70 + }, + "00000_00002-00183_00004" : { + "minimal_similarity" : 0.3829787234042553, + "maximum_similarity" : 0.46956521739130436, + "matched_token_number" : 54 + }, + "00186_00002-00204_00001" : { + "minimal_similarity" : 0.5362318840579711, + "maximum_similarity" : 0.6166666666666667, + "matched_token_number" : 74 + }, + "00135_00001-00177_00003" : { + "minimal_similarity" : 0.5273972602739726, + "maximum_similarity" : 0.6260162601626016, + "matched_token_number" : 77 + }, + "00111_00001-00198_00001" : { + "minimal_similarity" : 0.4342105263157895, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00127_00002-00193_00001" : { + "minimal_similarity" : 0.5488721804511278, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00014_00001-00138_00001" : { + "minimal_similarity" : 0.4152542372881356, + "maximum_similarity" : 0.4537037037037037, + "matched_token_number" : 49 + }, + "00153_00001-00204_00001" : { + "minimal_similarity" : 0.5447154471544715, + "maximum_similarity" : 0.5583333333333333, + "matched_token_number" : 67 + }, + "00145_00001-00200_00002" : { + "minimal_similarity" : 0.5658914728682171, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00000_00005-00201_00001" : { + "minimal_similarity" : 0.25833333333333336, + "maximum_similarity" : 0.3563218390804598, + "matched_token_number" : 31 + }, + "00013_00002-00113_00002" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.6421052631578947, + "matched_token_number" : 61 + }, + "00121_00001-00156_00003" : { + "minimal_similarity" : 0.49264705882352944, + "maximum_similarity" : 0.49264705882352944, + "matched_token_number" : 67 + }, + "00138_00001-00145_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00121_00001-00156_00002" : { + "minimal_similarity" : 0.49264705882352944, + "maximum_similarity" : 0.49264705882352944, + "matched_token_number" : 67 + }, + "00125_00001-00135_00001" : { + "minimal_similarity" : 0.5273972602739726, + "maximum_similarity" : 0.6260162601626016, + "matched_token_number" : 77 + }, + "00141_00002-00196_00001" : { + "minimal_similarity" : 0.17034700315457413, + "maximum_similarity" : 0.5, + "matched_token_number" : 54 + }, + "00000_00001-00183_00004" : { + "minimal_similarity" : 0.375886524822695, + "maximum_similarity" : 0.5408163265306123, + "matched_token_number" : 53 + }, + "00187_00001-00199_00001" : { + "minimal_similarity" : 0.48484848484848486, + "maximum_similarity" : 0.6736842105263158, + "matched_token_number" : 64 + }, + "00141_00002-00197_00001" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.6111111111111112, + "matched_token_number" : 66 + }, + "00193_00001-00198_00001" : { + "minimal_similarity" : 0.5328947368421053, + "maximum_similarity" : 0.6090225563909775, + "matched_token_number" : 81 + }, + "00127_00002-00194_00001" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00014_00001-00133_00001" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00125_00001-00193_00001" : { + "minimal_similarity" : 0.5488721804511278, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00183_00004-00198_00001" : { + "minimal_similarity" : 0.506578947368421, + "maximum_similarity" : 0.5460992907801419, + "matched_token_number" : 77 + }, + "00119_00001-00195_00002" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 56 + }, + "00119_00001-00195_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 56 + }, + "00133_00001-00198_00001" : { + "minimal_similarity" : 0.4342105263157895, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00154_00002-00160_00001" : { + "minimal_similarity" : 0.5661764705882353, + "maximum_similarity" : 0.6470588235294118, + "matched_token_number" : 77 + }, + "00134_00001-00160_00001" : { + "minimal_similarity" : 0.38235294117647056, + "maximum_similarity" : 0.6419753086419753, + "matched_token_number" : 52 + }, + "00095_00003-00113_00002" : { + "minimal_similarity" : 0.4069767441860465, + "maximum_similarity" : 0.5737704918032787, + "matched_token_number" : 70 + }, + "00183_00004-00186_00004" : { + "minimal_similarity" : 0.5035460992907801, + "maximum_similarity" : 0.6698113207547169, + "matched_token_number" : 71 + }, + "00125_00001-00199_00001" : { + "minimal_similarity" : 0.5121951219512195, + "maximum_similarity" : 0.6631578947368421, + "matched_token_number" : 63 + }, + "00183_00004-00186_00002" : { + "minimal_similarity" : 0.5319148936170213, + "maximum_similarity" : 0.5434782608695652, + "matched_token_number" : 75 + }, + "00097_00002-00154_00002" : { + "minimal_similarity" : 0.5126050420168067, + "maximum_similarity" : 0.5754716981132075, + "matched_token_number" : 61 + }, + "00111_00001-00193_00001" : { + "minimal_similarity" : 0.5488721804511278, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00113_00002-00203_00002" : { + "minimal_similarity" : 0.5766423357664233, + "maximum_similarity" : 0.6475409836065574, + "matched_token_number" : 79 + }, + "00154_00002-00198_00001" : { + "minimal_similarity" : 0.40789473684210525, + "maximum_similarity" : 0.5210084033613446, + "matched_token_number" : 62 + }, + "00014_00001-00192_00002" : { + "minimal_similarity" : 0.5190839694656488, + "maximum_similarity" : 0.6296296296296297, + "matched_token_number" : 68 + }, + "00014_00001-00192_00001" : { + "minimal_similarity" : 0.41935483870967744, + "maximum_similarity" : 0.6018518518518519, + "matched_token_number" : 65 + }, + "00145_00001-00147_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00127_00002-00198_00001" : { + "minimal_similarity" : 0.4342105263157895, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00178_00002-00183_00004" : { + "minimal_similarity" : 0.48226950354609927, + "maximum_similarity" : 0.5528455284552846, + "matched_token_number" : 68 + }, + "00014_00001-00195_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 56 + }, + "00014_00001-00077_00001" : { + "minimal_similarity" : 0.3375, + "maximum_similarity" : 0.5, + "matched_token_number" : 54 + }, + "00186_00002-00187_00001" : { + "minimal_similarity" : 0.6304347826086957, + "maximum_similarity" : 0.6590909090909091, + "matched_token_number" : 87 + }, + "00138_00001-00203_00002" : { + "minimal_similarity" : 0.46715328467153283, + "maximum_similarity" : 0.5423728813559322, + "matched_token_number" : 64 + }, + "00120_00001-00154_00002" : { + "minimal_similarity" : 0.5294117647058824, + "maximum_similarity" : 0.5338983050847458, + "matched_token_number" : 63 + }, + "00111_00001-00186_00002" : { + "minimal_similarity" : 0.4782608695652174, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00138_00001-00140_00001" : { + "minimal_similarity" : 0.423728813559322, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00014_00001-00195_00002" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 56 + }, + "00111_00001-00186_00004" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.5283018867924528, + "matched_token_number" : 56 + }, + "00077_00001-00160_00001" : { + "minimal_similarity" : 0.4125, + "maximum_similarity" : 0.4852941176470588, + "matched_token_number" : 66 + }, + "00192_00001-00199_00001" : { + "minimal_similarity" : 0.4258064516129032, + "maximum_similarity" : 0.6947368421052632, + "matched_token_number" : 66 + }, + "00000_00001-00031_00002" : { + "minimal_similarity" : 0.45918367346938777, + "maximum_similarity" : 0.4891304347826087, + "matched_token_number" : 45 + }, + "00000_00001-00031_00003" : { + "minimal_similarity" : 0.5612244897959183, + "maximum_similarity" : 0.6470588235294118, + "matched_token_number" : 55 + }, + "00126_00002-00195_00001" : { + "minimal_similarity" : 0.9830508474576272, + "maximum_similarity" : 0.9830508474576272, + "matched_token_number" : 116 + }, + "00126_00002-00195_00002" : { + "minimal_similarity" : 0.9830508474576272, + "maximum_similarity" : 0.9830508474576272, + "matched_token_number" : 116 + }, + "00031_00003-00141_00002" : { + "minimal_similarity" : 0.5092592592592593, + "maximum_similarity" : 0.6470588235294118, + "matched_token_number" : 55 + }, + "00125_00001-00198_00001" : { + "minimal_similarity" : 0.4342105263157895, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00131_00005-00192_00002" : { + "minimal_similarity" : 0.5375, + "maximum_similarity" : 0.6564885496183206, + "matched_token_number" : 86 + }, + "00077_00001-00156_00002" : { + "minimal_similarity" : 0.3625, + "maximum_similarity" : 0.4264705882352941, + "matched_token_number" : 58 + }, + "00131_00005-00192_00001" : { + "minimal_similarity" : 0.55, + "maximum_similarity" : 0.567741935483871, + "matched_token_number" : 88 + }, + "00077_00001-00156_00003" : { + "minimal_similarity" : 0.3625, + "maximum_similarity" : 0.4264705882352941, + "matched_token_number" : 58 + }, + "00129_00008-00135_00001" : { + "minimal_similarity" : 0.41702127659574467, + "maximum_similarity" : 0.6712328767123288, + "matched_token_number" : 98 + }, + "00014_00001-00137_00002" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00119_00001-00199_00001" : { + "minimal_similarity" : 0.5092592592592593, + "maximum_similarity" : 0.5789473684210527, + "matched_token_number" : 55 + }, + "00156_00003-00198_00001" : { + "minimal_similarity" : 0.48026315789473684, + "maximum_similarity" : 0.5367647058823529, + "matched_token_number" : 73 + }, + "00192_00001-00196_00001" : { + "minimal_similarity" : 0.23659305993690852, + "maximum_similarity" : 0.4838709677419355, + "matched_token_number" : 75 + }, + "00000_00002-00014_00001" : { + "minimal_similarity" : 0.4782608695652174, + "maximum_similarity" : 0.5092592592592593, + "matched_token_number" : 55 + }, + "00141_00002-00155_00001" : { + "minimal_similarity" : 0.5370370370370371, + "maximum_similarity" : 0.6666666666666666, + "matched_token_number" : 58 + }, + "00092_00001-00130_00002" : { + "minimal_similarity" : 0.423728813559322, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00140_00001-00160_00001" : { + "minimal_similarity" : 0.4117647058823529, + "maximum_similarity" : 0.6436781609195402, + "matched_token_number" : 56 + }, + "00000_00001-00192_00001" : { + "minimal_similarity" : 0.38064516129032255, + "maximum_similarity" : 0.6020408163265306, + "matched_token_number" : 59 + }, + "00000_00005-00140_00001" : { + "minimal_similarity" : 0.4166666666666667, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00000_00001-00192_00002" : { + "minimal_similarity" : 0.4122137404580153, + "maximum_similarity" : 0.5510204081632653, + "matched_token_number" : 54 + }, + "00141_00002-00153_00001" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00031_00003-00142_00001" : { + "minimal_similarity" : 0.3728813559322034, + "maximum_similarity" : 0.5176470588235295, + "matched_token_number" : 44 + }, + "00126_00002-00192_00001" : { + "minimal_similarity" : 0.4129032258064516, + "maximum_similarity" : 0.5423728813559322, + "matched_token_number" : 64 + }, + "00031_00003-00200_00002" : { + "minimal_similarity" : 0.3798449612403101, + "maximum_similarity" : 0.5764705882352941, + "matched_token_number" : 49 + }, + "00044_00002-00198_00001" : { + "minimal_similarity" : 0.4144736842105263, + "maximum_similarity" : 0.6363636363636364, + "matched_token_number" : 63 + }, + "00154_00002-00199_00001" : { + "minimal_similarity" : 0.48739495798319327, + "maximum_similarity" : 0.6105263157894737, + "matched_token_number" : 58 + }, + "00031_00002-00155_00001" : { + "minimal_similarity" : 0.5108695652173914, + "maximum_similarity" : 0.5402298850574713, + "matched_token_number" : 47 + }, + "00126_00002-00192_00002" : { + "minimal_similarity" : 0.4580152671755725, + "maximum_similarity" : 0.5084745762711864, + "matched_token_number" : 60 + }, + "00113_00002-00202_00003" : { + "minimal_similarity" : 0.4326241134751773, + "maximum_similarity" : 0.5, + "matched_token_number" : 61 + }, + "00113_00002-00202_00002" : { + "minimal_similarity" : 0.46808510638297873, + "maximum_similarity" : 0.5409836065573771, + "matched_token_number" : 66 + }, + "00097_00002-00198_00001" : { + "minimal_similarity" : 0.375, + "maximum_similarity" : 0.5377358490566038, + "matched_token_number" : 57 + }, + "00186_00002-00200_00002" : { + "minimal_similarity" : 0.4420289855072464, + "maximum_similarity" : 0.4728682170542636, + "matched_token_number" : 61 + }, + "00013_00002-00121_00001" : { + "minimal_similarity" : 0.47794117647058826, + "maximum_similarity" : 0.6842105263157895, + "matched_token_number" : 65 + }, + "00138_00001-00200_00002" : { + "minimal_similarity" : 0.40310077519379844, + "maximum_similarity" : 0.4406779661016949, + "matched_token_number" : 52 + }, + "00141_00002-00154_00002" : { + "minimal_similarity" : 0.5714285714285714, + "maximum_similarity" : 0.6296296296296297, + "matched_token_number" : 68 + }, + "00031_00003-00201_00001" : { + "minimal_similarity" : 0.4367816091954023, + "maximum_similarity" : 0.4470588235294118, + "matched_token_number" : 38 + }, + "00111_00001-00194_00001" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00005_00002-00156_00003" : { + "minimal_similarity" : 0.3625, + "maximum_similarity" : 0.4264705882352941, + "matched_token_number" : 58 + }, + "00005_00002-00156_00002" : { + "minimal_similarity" : 0.3625, + "maximum_similarity" : 0.4264705882352941, + "matched_token_number" : 58 + }, + "00031_00002-00154_00002" : { + "minimal_similarity" : 0.44537815126050423, + "maximum_similarity" : 0.5760869565217391, + "matched_token_number" : 53 + }, + "00129_00008-00134_00001" : { + "minimal_similarity" : 0.2, + "maximum_similarity" : 0.5802469135802469, + "matched_token_number" : 47 + }, + "00131_00005-00193_00001" : { + "minimal_similarity" : 0.44375, + "maximum_similarity" : 0.5338345864661654, + "matched_token_number" : 71 + }, + "00183_00004-00194_00001" : { + "minimal_similarity" : 0.425531914893617, + "maximum_similarity" : 0.5555555555555556, + "matched_token_number" : 60 + }, + "00097_00002-00197_00001" : { + "minimal_similarity" : 0.42424242424242425, + "maximum_similarity" : 0.5283018867924528, + "matched_token_number" : 56 + }, + "00014_00001-00031_00002" : { + "minimal_similarity" : 0.5185185185185185, + "maximum_similarity" : 0.6086956521739131, + "matched_token_number" : 56 + }, + "00014_00001-00136_00002" : { + "minimal_similarity" : 0.35555555555555557, + "maximum_similarity" : 0.5925925925925926, + "matched_token_number" : 64 + }, + "00014_00001-00031_00003" : { + "minimal_similarity" : 0.5092592592592593, + "maximum_similarity" : 0.6470588235294118, + "matched_token_number" : 55 + }, + "00044_00002-00199_00001" : { + "minimal_similarity" : 0.45454545454545453, + "maximum_similarity" : 0.47368421052631576, + "matched_token_number" : 45 + }, + "00178_00002-00202_00002" : { + "minimal_similarity" : 0.46808510638297873, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00121_00001-00125_00001" : { + "minimal_similarity" : 0.6985294117647058, + "maximum_similarity" : 0.7723577235772358, + "matched_token_number" : 95 + }, + "00125_00001-00197_00001" : { + "minimal_similarity" : 0.5909090909090909, + "maximum_similarity" : 0.6341463414634146, + "matched_token_number" : 78 + }, + "00130_00002-00156_00003" : { + "minimal_similarity" : 0.36764705882352944, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00119_00001-00198_00001" : { + "minimal_similarity" : 0.3618421052631579, + "maximum_similarity" : 0.5092592592592593, + "matched_token_number" : 55 + }, + "00134_00001-00135_00001" : { + "minimal_similarity" : 0.3767123287671233, + "maximum_similarity" : 0.6790123456790124, + "matched_token_number" : 55 + }, + "00130_00002-00156_00002" : { + "minimal_similarity" : 0.36764705882352944, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00184_00002-00201_00001" : { + "minimal_similarity" : 0.3617021276595745, + "maximum_similarity" : 0.39080459770114945, + "matched_token_number" : 34 + }, + "00131_00005-00156_00002" : { + "minimal_similarity" : 0.3625, + "maximum_similarity" : 0.4264705882352941, + "matched_token_number" : 58 + }, + "00196_00001-00199_00001" : { + "minimal_similarity" : 0.17034700315457413, + "maximum_similarity" : 0.5684210526315789, + "matched_token_number" : 54 + }, + "00131_00005-00156_00003" : { + "minimal_similarity" : 0.3625, + "maximum_similarity" : 0.4264705882352941, + "matched_token_number" : 58 + }, + "00031_00002-00193_00001" : { + "minimal_similarity" : 0.39849624060150374, + "maximum_similarity" : 0.5760869565217391, + "matched_token_number" : 53 + }, + "00197_00001-00199_00001" : { + "minimal_similarity" : 0.48484848484848486, + "maximum_similarity" : 0.6736842105263158, + "matched_token_number" : 64 + }, + "00193_00001-00194_00001" : { + "minimal_similarity" : 0.518796992481203, + "maximum_similarity" : 0.6388888888888888, + "matched_token_number" : 69 + }, + "00113_00002-00187_00001" : { + "minimal_similarity" : 0.5909090909090909, + "maximum_similarity" : 0.639344262295082, + "matched_token_number" : 78 + }, + "00000_00005-00204_00001" : { + "minimal_similarity" : 0.43333333333333335, + "maximum_similarity" : 0.43333333333333335, + "matched_token_number" : 52 + }, + "00031_00003-00113_00002" : { + "minimal_similarity" : 0.4426229508196721, + "maximum_similarity" : 0.6352941176470588, + "matched_token_number" : 54 + }, + "00097_00002-00156_00002" : { + "minimal_similarity" : 0.39705882352941174, + "maximum_similarity" : 0.5094339622641509, + "matched_token_number" : 54 + }, + "00097_00002-00156_00003" : { + "minimal_similarity" : 0.39705882352941174, + "maximum_similarity" : 0.5094339622641509, + "matched_token_number" : 54 + }, + "00120_00001-00160_00001" : { + "minimal_similarity" : 0.47058823529411764, + "maximum_similarity" : 0.5423728813559322, + "matched_token_number" : 64 + }, + "00111_00001-00121_00001" : { + "minimal_similarity" : 0.6985294117647058, + "maximum_similarity" : 0.7723577235772358, + "matched_token_number" : 95 + }, + "00198_00001-00199_00001" : { + "minimal_similarity" : 0.4144736842105263, + "maximum_similarity" : 0.6631578947368421, + "matched_token_number" : 63 + }, + "00155_00001-00201_00001" : { + "minimal_similarity" : 0.3793103448275862, + "maximum_similarity" : 0.3793103448275862, + "matched_token_number" : 33 + }, + "00097_00002-00196_00001" : { + "minimal_similarity" : 0.1861198738170347, + "maximum_similarity" : 0.5566037735849056, + "matched_token_number" : 59 + }, + "00000_00001-00121_00001" : { + "minimal_similarity" : 0.3382352941176471, + "maximum_similarity" : 0.46938775510204084, + "matched_token_number" : 46 + }, + "00000_00001-00187_00001" : { + "minimal_similarity" : 0.4090909090909091, + "maximum_similarity" : 0.5510204081632653, + "matched_token_number" : 54 + }, + "00138_00001-00141_00002" : { + "minimal_similarity" : 0.4152542372881356, + "maximum_similarity" : 0.4537037037037037, + "matched_token_number" : 49 + }, + "00000_00005-00147_00001" : { + "minimal_similarity" : 0.38333333333333336, + "maximum_similarity" : 0.3898305084745763, + "matched_token_number" : 46 + }, + "00125_00001-00131_00005" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00095_00003-00111_00001" : { + "minimal_similarity" : 0.42441860465116277, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00077_00001-00121_00001" : { + "minimal_similarity" : 0.475, + "maximum_similarity" : 0.5588235294117647, + "matched_token_number" : 76 + }, + "00000_00002-00147_00001" : { + "minimal_similarity" : 0.4322033898305085, + "maximum_similarity" : 0.4434782608695652, + "matched_token_number" : 51 + }, + "00130_00002-00183_00004" : { + "minimal_similarity" : 0.3829787234042553, + "maximum_similarity" : 0.6206896551724138, + "matched_token_number" : 54 + }, + "00014_00001-00131_00005" : { + "minimal_similarity" : 0.3375, + "maximum_similarity" : 0.5, + "matched_token_number" : 54 + }, + "00121_00001-00192_00002" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.5190839694656488, + "matched_token_number" : 68 + }, + "00121_00001-00192_00001" : { + "minimal_similarity" : 0.47096774193548385, + "maximum_similarity" : 0.5367647058823529, + "matched_token_number" : 73 + }, + "00187_00001-00195_00002" : { + "minimal_similarity" : 0.4393939393939394, + "maximum_similarity" : 0.4915254237288136, + "matched_token_number" : 58 + }, + "00178_00002-00202_00003" : { + "minimal_similarity" : 0.4326241134751773, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00186_00002-00201_00001" : { + "minimal_similarity" : 0.2463768115942029, + "maximum_similarity" : 0.39080459770114945, + "matched_token_number" : 34 + }, + "00187_00001-00195_00001" : { + "minimal_similarity" : 0.4393939393939394, + "maximum_similarity" : 0.4915254237288136, + "matched_token_number" : 58 + }, + "00192_00002-00200_00002" : { + "minimal_similarity" : 0.5801526717557252, + "maximum_similarity" : 0.5891472868217055, + "matched_token_number" : 76 + }, + "00129_00008-00131_00005" : { + "minimal_similarity" : 0.3021276595744681, + "maximum_similarity" : 0.44375, + "matched_token_number" : 71 + }, + "00077_00001-00195_00001" : { + "minimal_similarity" : 0.46875, + "maximum_similarity" : 0.635593220338983, + "matched_token_number" : 75 + }, + "00077_00001-00195_00002" : { + "minimal_similarity" : 0.46875, + "maximum_similarity" : 0.635593220338983, + "matched_token_number" : 75 + }, + "00120_00001-00199_00001" : { + "minimal_similarity" : 0.4830508474576271, + "maximum_similarity" : 0.6, + "matched_token_number" : 57 + }, + "00125_00001-00136_00002" : { + "minimal_similarity" : 0.4, + "maximum_similarity" : 0.5853658536585366, + "matched_token_number" : 72 + }, + "00014_00001-00197_00001" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.6111111111111112, + "matched_token_number" : 66 + }, + "00000_00005-00113_00002" : { + "minimal_similarity" : 0.4672131147540984, + "maximum_similarity" : 0.475, + "matched_token_number" : 57 + }, + "00193_00001-00199_00001" : { + "minimal_similarity" : 0.44360902255639095, + "maximum_similarity" : 0.6210526315789474, + "matched_token_number" : 59 + }, + "00031_00003-00145_00001" : { + "minimal_similarity" : 0.43902439024390244, + "maximum_similarity" : 0.6352941176470588, + "matched_token_number" : 54 + }, + "00000_00002-00113_00002" : { + "minimal_similarity" : 0.45901639344262296, + "maximum_similarity" : 0.48695652173913045, + "matched_token_number" : 56 + }, + "00120_00001-00192_00001" : { + "minimal_similarity" : 0.4129032258064516, + "maximum_similarity" : 0.5423728813559322, + "matched_token_number" : 64 + }, + "00120_00001-00192_00002" : { + "minimal_similarity" : 0.4580152671755725, + "maximum_similarity" : 0.5084745762711864, + "matched_token_number" : 60 + }, + "00031_00002-00198_00001" : { + "minimal_similarity" : 0.29605263157894735, + "maximum_similarity" : 0.4891304347826087, + "matched_token_number" : 45 + }, + "00156_00003-00197_00001" : { + "minimal_similarity" : 0.5367647058823529, + "maximum_similarity" : 0.553030303030303, + "matched_token_number" : 73 + }, + "00095_00003-00177_00003" : { + "minimal_similarity" : 0.42441860465116277, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00186_00004-00195_00001" : { + "minimal_similarity" : 0.423728813559322, + "maximum_similarity" : 0.4716981132075472, + "matched_token_number" : 50 + }, + "00186_00004-00195_00002" : { + "minimal_similarity" : 0.423728813559322, + "maximum_similarity" : 0.4716981132075472, + "matched_token_number" : 50 + }, + "00119_00001-00137_00002" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00000_00001-00153_00001" : { + "minimal_similarity" : 0.43902439024390244, + "maximum_similarity" : 0.5510204081632653, + "matched_token_number" : 54 + }, + "00113_00002-00147_00001" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00195_00001-00199_00001" : { + "minimal_similarity" : 0.4830508474576271, + "maximum_similarity" : 0.6, + "matched_token_number" : 57 + }, + "00000_00001-00126_00002" : { + "minimal_similarity" : 0.4406779661016949, + "maximum_similarity" : 0.5306122448979592, + "matched_token_number" : 52 + }, + "00137_00002-00194_00001" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00133_00001-00135_00001" : { + "minimal_similarity" : 0.5273972602739726, + "maximum_similarity" : 0.6260162601626016, + "matched_token_number" : 77 + }, + "00113_00002-00204_00001" : { + "minimal_similarity" : 0.5491803278688525, + "maximum_similarity" : 0.5583333333333333, + "matched_token_number" : 67 + }, + "00160_00001-00200_00002" : { + "minimal_similarity" : 0.6029411764705882, + "maximum_similarity" : 0.6356589147286822, + "matched_token_number" : 82 + }, + "00147_00001-00177_00003" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00000_00002-00142_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.48695652173913045, + "matched_token_number" : 56 + }, + "00077_00001-00126_00002" : { + "minimal_similarity" : 0.46875, + "maximum_similarity" : 0.635593220338983, + "matched_token_number" : 75 + }, + "00000_00005-00142_00001" : { + "minimal_similarity" : 0.49166666666666664, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00120_00001-00125_00001" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00121_00001-00197_00001" : { + "minimal_similarity" : 0.5514705882352942, + "maximum_similarity" : 0.5681818181818182, + "matched_token_number" : 75 + }, + "00031_00003-00204_00001" : { + "minimal_similarity" : 0.49166666666666664, + "maximum_similarity" : 0.6941176470588235, + "matched_token_number" : 59 + }, + "00136_00002-00196_00001" : { + "minimal_similarity" : 0.17981072555205047, + "maximum_similarity" : 0.31666666666666665, + "matched_token_number" : 57 + }, + "00005_00002-00153_00001" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00005_00002-00113_00002" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6885245901639344, + "matched_token_number" : 84 + }, + "00192_00001-00194_00001" : { + "minimal_similarity" : 0.41935483870967744, + "maximum_similarity" : 0.6018518518518519, + "matched_token_number" : 65 + }, + "00127_00002-00155_00001" : { + "minimal_similarity" : 0.5447154471544715, + "maximum_similarity" : 0.7701149425287356, + "matched_token_number" : 67 + }, + "00013_00002-00155_00001" : { + "minimal_similarity" : 0.49473684210526314, + "maximum_similarity" : 0.5402298850574713, + "matched_token_number" : 47 + }, + "00120_00001-00194_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 56 + }, + "00201_00001-00203_00002" : { + "minimal_similarity" : 0.29927007299270075, + "maximum_similarity" : 0.47126436781609193, + "matched_token_number" : 41 + }, + "00145_00001-00177_00003" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00097_00002-00127_00002" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5754716981132075, + "matched_token_number" : 61 + }, + "00031_00003-00147_00001" : { + "minimal_similarity" : 0.4067796610169492, + "maximum_similarity" : 0.5647058823529412, + "matched_token_number" : 48 + }, + "00186_00004-00197_00001" : { + "minimal_similarity" : 0.5075757575757576, + "maximum_similarity" : 0.6320754716981132, + "matched_token_number" : 67 + }, + "00136_00002-00199_00001" : { + "minimal_similarity" : 0.31666666666666665, + "maximum_similarity" : 0.6, + "matched_token_number" : 57 + }, + "00160_00001-00202_00002" : { + "minimal_similarity" : 0.5673758865248227, + "maximum_similarity" : 0.5882352941176471, + "matched_token_number" : 80 + }, + "00120_00001-00197_00001" : { + "minimal_similarity" : 0.4393939393939394, + "maximum_similarity" : 0.4915254237288136, + "matched_token_number" : 58 + }, + "00147_00001-00204_00001" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.5084745762711864, + "matched_token_number" : 60 + }, + "00111_00001-00153_00001" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00156_00003-00192_00002" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.5190839694656488, + "matched_token_number" : 68 + }, + "00156_00003-00195_00002" : { + "minimal_similarity" : 0.34558823529411764, + "maximum_similarity" : 0.3983050847457627, + "matched_token_number" : 47 + }, + "00156_00003-00195_00001" : { + "minimal_similarity" : 0.34558823529411764, + "maximum_similarity" : 0.3983050847457627, + "matched_token_number" : 47 + }, + "00155_00001-00178_00002" : { + "minimal_similarity" : 0.5447154471544715, + "maximum_similarity" : 0.7701149425287356, + "matched_token_number" : 67 + }, + "00156_00003-00192_00001" : { + "minimal_similarity" : 0.432258064516129, + "maximum_similarity" : 0.49264705882352944, + "matched_token_number" : 67 + }, + "00138_00001-00178_00002" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00125_00001-00160_00001" : { + "minimal_similarity" : 0.6102941176470589, + "maximum_similarity" : 0.6747967479674797, + "matched_token_number" : 83 + }, + "00160_00001-00202_00003" : { + "minimal_similarity" : 0.5531914893617021, + "maximum_similarity" : 0.5735294117647058, + "matched_token_number" : 78 + }, + "00133_00001-00137_00002" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00121_00001-00199_00001" : { + "minimal_similarity" : 0.39705882352941174, + "maximum_similarity" : 0.5684210526315789, + "matched_token_number" : 54 + }, + "00127_00002-00192_00001" : { + "minimal_similarity" : 0.44516129032258067, + "maximum_similarity" : 0.5609756097560976, + "matched_token_number" : 69 + }, + "00127_00002-00192_00002" : { + "minimal_similarity" : 0.5267175572519084, + "maximum_similarity" : 0.5609756097560976, + "matched_token_number" : 69 + }, + "00129_00008-00195_00001" : { + "minimal_similarity" : 0.2723404255319149, + "maximum_similarity" : 0.5423728813559322, + "matched_token_number" : 64 + }, + "00126_00002-00155_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.6436781609195402, + "matched_token_number" : 56 + }, + "00129_00008-00195_00002" : { + "minimal_similarity" : 0.2723404255319149, + "maximum_similarity" : 0.5423728813559322, + "matched_token_number" : 64 + }, + "00136_00002-00160_00001" : { + "minimal_similarity" : 0.45, + "maximum_similarity" : 0.5955882352941176, + "matched_token_number" : 81 + }, + "00153_00001-00203_00002" : { + "minimal_similarity" : 0.5766423357664233, + "maximum_similarity" : 0.6422764227642277, + "matched_token_number" : 79 + }, + "00121_00001-00127_00002" : { + "minimal_similarity" : 0.6985294117647058, + "maximum_similarity" : 0.7723577235772358, + "matched_token_number" : 95 + }, + "00092_00001-00193_00001" : { + "minimal_similarity" : 0.45864661654135336, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00193_00001-00196_00001" : { + "minimal_similarity" : 0.1892744479495268, + "maximum_similarity" : 0.45112781954887216, + "matched_token_number" : 60 + }, + "00137_00002-00160_00001" : { + "minimal_similarity" : 0.6102941176470589, + "maximum_similarity" : 0.6747967479674797, + "matched_token_number" : 83 + }, + "00031_00002-00121_00001" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.6630434782608695, + "matched_token_number" : 61 + }, + "00141_00002-00195_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 56 + }, + "00044_00002-00134_00001" : { + "minimal_similarity" : 0.37373737373737376, + "maximum_similarity" : 0.4567901234567901, + "matched_token_number" : 37 + }, + "00141_00002-00195_00002" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 56 + }, + "00111_00001-00155_00001" : { + "minimal_similarity" : 0.5447154471544715, + "maximum_similarity" : 0.7701149425287356, + "matched_token_number" : 67 + }, + "00097_00002-00129_00008" : { + "minimal_similarity" : 0.28085106382978725, + "maximum_similarity" : 0.6226415094339622, + "matched_token_number" : 66 + }, + "00153_00001-00201_00001" : { + "minimal_similarity" : 0.3008130081300813, + "maximum_similarity" : 0.42528735632183906, + "matched_token_number" : 37 + }, + "00147_00001-00202_00003" : { + "minimal_similarity" : 0.40425531914893614, + "maximum_similarity" : 0.4830508474576271, + "matched_token_number" : 57 + }, + "00147_00001-00202_00002" : { + "minimal_similarity" : 0.40425531914893614, + "maximum_similarity" : 0.4830508474576271, + "matched_token_number" : 57 + }, + "00178_00002-00200_00002" : { + "minimal_similarity" : 0.5658914728682171, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00000_00002-00140_00001" : { + "minimal_similarity" : 0.45217391304347826, + "maximum_similarity" : 0.5977011494252874, + "matched_token_number" : 52 + }, + "00044_00002-00077_00001" : { + "minimal_similarity" : 0.3625, + "maximum_similarity" : 0.5858585858585859, + "matched_token_number" : 58 + }, + "00141_00002-00193_00001" : { + "minimal_similarity" : 0.518796992481203, + "maximum_similarity" : 0.6388888888888888, + "matched_token_number" : 69 + }, + "00121_00001-00160_00001" : { + "minimal_similarity" : 0.47794117647058826, + "maximum_similarity" : 0.47794117647058826, + "matched_token_number" : 65 + }, + "00000_00005-00202_00002" : { + "minimal_similarity" : 0.3900709219858156, + "maximum_similarity" : 0.4583333333333333, + "matched_token_number" : 55 + }, + "00092_00001-00129_00008" : { + "minimal_similarity" : 0.30638297872340425, + "maximum_similarity" : 0.6101694915254238, + "matched_token_number" : 72 + }, + "00000_00005-00202_00003" : { + "minimal_similarity" : 0.3617021276595745, + "maximum_similarity" : 0.425, + "matched_token_number" : 51 + }, + "00192_00002-00203_00002" : { + "minimal_similarity" : 0.635036496350365, + "maximum_similarity" : 0.6641221374045801, + "matched_token_number" : 87 + }, + "00194_00001-00199_00001" : { + "minimal_similarity" : 0.5092592592592593, + "maximum_similarity" : 0.5789473684210527, + "matched_token_number" : 55 + }, + "00077_00001-00198_00001" : { + "minimal_similarity" : 0.49375, + "maximum_similarity" : 0.5197368421052632, + "matched_token_number" : 79 + }, + "00031_00002-00195_00002" : { + "minimal_similarity" : 0.4322033898305085, + "maximum_similarity" : 0.5543478260869565, + "matched_token_number" : 51 + }, + "00131_00005-00154_00002" : { + "minimal_similarity" : 0.49375, + "maximum_similarity" : 0.6638655462184874, + "matched_token_number" : 79 + }, + "00031_00002-00195_00001" : { + "minimal_similarity" : 0.4322033898305085, + "maximum_similarity" : 0.5543478260869565, + "matched_token_number" : 51 + }, + "00111_00001-00126_00002" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00187_00001-00197_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 132 + }, + "00000_00002-00111_00001" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.48695652173913045, + "matched_token_number" : 56 + }, + "00125_00001-00133_00001" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00119_00001-00134_00001" : { + "minimal_similarity" : 0.4722222222222222, + "maximum_similarity" : 0.6296296296296297, + "matched_token_number" : 51 + }, + "00005_00002-00092_00001" : { + "minimal_similarity" : 0.45625, + "maximum_similarity" : 0.6186440677966102, + "matched_token_number" : 73 + }, + "00013_00002-00184_00003" : { + "minimal_similarity" : 0.49473684210526314, + "maximum_similarity" : 0.5, + "matched_token_number" : 47 + }, + "00013_00002-00184_00002" : { + "minimal_similarity" : 0.49473684210526314, + "maximum_similarity" : 0.5, + "matched_token_number" : 47 + }, + "00129_00008-00197_00001" : { + "minimal_similarity" : 0.37446808510638296, + "maximum_similarity" : 0.6666666666666666, + "matched_token_number" : 88 + }, + "00044_00002-00136_00002" : { + "minimal_similarity" : 0.34444444444444444, + "maximum_similarity" : 0.6262626262626263, + "matched_token_number" : 62 + }, + "00000_00005-00145_00001" : { + "minimal_similarity" : 0.4634146341463415, + "maximum_similarity" : 0.475, + "matched_token_number" : 57 + }, + "00147_00001-00200_00002" : { + "minimal_similarity" : 0.40310077519379844, + "maximum_similarity" : 0.4406779661016949, + "matched_token_number" : 52 + }, + "00095_00003-00204_00001" : { + "minimal_similarity" : 0.38953488372093026, + "maximum_similarity" : 0.5583333333333333, + "matched_token_number" : 67 + }, + "00129_00008-00199_00001" : { + "minimal_similarity" : 0.2425531914893617, + "maximum_similarity" : 0.6, + "matched_token_number" : 57 + }, + "00077_00001-00197_00001" : { + "minimal_similarity" : 0.49375, + "maximum_similarity" : 0.5984848484848485, + "matched_token_number" : 79 + }, + "00126_00002-00154_00002" : { + "minimal_similarity" : 0.5294117647058824, + "maximum_similarity" : 0.5338983050847458, + "matched_token_number" : 63 + }, + "00134_00001-00138_00001" : { + "minimal_similarity" : 0.3050847457627119, + "maximum_similarity" : 0.4444444444444444, + "matched_token_number" : 36 + }, + "00092_00001-00194_00001" : { + "minimal_similarity" : 0.4152542372881356, + "maximum_similarity" : 0.4537037037037037, + "matched_token_number" : 49 + }, + "00000_00005-00111_00001" : { + "minimal_similarity" : 0.4634146341463415, + "maximum_similarity" : 0.475, + "matched_token_number" : 57 + }, + "00184_00002-00204_00001" : { + "minimal_similarity" : 0.5416666666666666, + "maximum_similarity" : 0.6914893617021277, + "matched_token_number" : 65 + }, + "00097_00002-00120_00001" : { + "minimal_similarity" : 0.4576271186440678, + "maximum_similarity" : 0.5094339622641509, + "matched_token_number" : 54 + }, + "00000_00003-00131_00005" : { + "minimal_similarity" : 0.40625, + "maximum_similarity" : 0.5462184873949579, + "matched_token_number" : 65 + }, + "00136_00002-00192_00001" : { + "minimal_similarity" : 0.46111111111111114, + "maximum_similarity" : 0.535483870967742, + "matched_token_number" : 83 + }, + "00136_00002-00192_00002" : { + "minimal_similarity" : 0.4222222222222222, + "maximum_similarity" : 0.5801526717557252, + "matched_token_number" : 76 + }, + "00120_00001-00195_00002" : { + "minimal_similarity" : 0.9830508474576272, + "maximum_similarity" : 0.9830508474576272, + "matched_token_number" : 116 + }, + "00120_00001-00195_00001" : { + "minimal_similarity" : 0.9830508474576272, + "maximum_similarity" : 0.9830508474576272, + "matched_token_number" : 116 + }, + "00137_00002-00192_00001" : { + "minimal_similarity" : 0.44516129032258067, + "maximum_similarity" : 0.5609756097560976, + "matched_token_number" : 69 + }, + "00186_00004-00198_00001" : { + "minimal_similarity" : 0.39473684210526316, + "maximum_similarity" : 0.5660377358490566, + "matched_token_number" : 60 + }, + "00129_00008-00160_00001" : { + "minimal_similarity" : 0.3659574468085106, + "maximum_similarity" : 0.6323529411764706, + "matched_token_number" : 86 + }, + "00000_00001-00156_00002" : { + "minimal_similarity" : 0.29411764705882354, + "maximum_similarity" : 0.40816326530612246, + "matched_token_number" : 40 + }, + "00000_00001-00156_00003" : { + "minimal_similarity" : 0.29411764705882354, + "maximum_similarity" : 0.40816326530612246, + "matched_token_number" : 40 + }, + "00194_00001-00197_00001" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.6111111111111112, + "matched_token_number" : 66 + }, + "00187_00001-00192_00001" : { + "minimal_similarity" : 0.7612903225806451, + "maximum_similarity" : 0.8939393939393939, + "matched_token_number" : 118 + }, + "00187_00001-00192_00002" : { + "minimal_similarity" : 0.7878787878787878, + "maximum_similarity" : 0.7938931297709924, + "matched_token_number" : 104 + }, + "00137_00002-00192_00002" : { + "minimal_similarity" : 0.5267175572519084, + "maximum_similarity" : 0.5609756097560976, + "matched_token_number" : 69 + }, + "00013_00002-00154_00002" : { + "minimal_similarity" : 0.47058823529411764, + "maximum_similarity" : 0.5894736842105263, + "matched_token_number" : 56 + }, + "00136_00002-00198_00001" : { + "minimal_similarity" : 0.5277777777777778, + "maximum_similarity" : 0.625, + "matched_token_number" : 95 + }, + "00135_00001-00137_00002" : { + "minimal_similarity" : 0.5273972602739726, + "maximum_similarity" : 0.6260162601626016, + "matched_token_number" : 77 + }, + "00119_00001-00130_00002" : { + "minimal_similarity" : 0.46296296296296297, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00121_00001-00195_00001" : { + "minimal_similarity" : 0.4632352941176471, + "maximum_similarity" : 0.5338983050847458, + "matched_token_number" : 63 + }, + "00121_00001-00195_00002" : { + "minimal_similarity" : 0.4632352941176471, + "maximum_similarity" : 0.5338983050847458, + "matched_token_number" : 63 + }, + "00130_00002-00186_00002" : { + "minimal_similarity" : 0.38405797101449274, + "maximum_similarity" : 0.6091954022988506, + "matched_token_number" : 53 + }, + "00195_00001-00197_00001" : { + "minimal_similarity" : 0.4393939393939394, + "maximum_similarity" : 0.4915254237288136, + "matched_token_number" : 58 + }, + "00005_00002-00183_00004" : { + "minimal_similarity" : 0.44375, + "maximum_similarity" : 0.5035460992907801, + "matched_token_number" : 71 + }, + "00000_00002-00202_00002" : { + "minimal_similarity" : 0.3617021276595745, + "maximum_similarity" : 0.4434782608695652, + "matched_token_number" : 51 + }, + "00130_00002-00186_00004" : { + "minimal_similarity" : 0.4716981132075472, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00160_00001-00178_00002" : { + "minimal_similarity" : 0.6102941176470589, + "maximum_similarity" : 0.6747967479674797, + "matched_token_number" : 83 + }, + "00155_00001-00204_00001" : { + "minimal_similarity" : 0.38333333333333336, + "maximum_similarity" : 0.5287356321839081, + "matched_token_number" : 46 + }, + "00000_00002-00202_00003" : { + "minimal_similarity" : 0.3333333333333333, + "maximum_similarity" : 0.40869565217391307, + "matched_token_number" : 47 + }, + "00000_00003-00130_00002" : { + "minimal_similarity" : 0.4369747899159664, + "maximum_similarity" : 0.5977011494252874, + "matched_token_number" : 52 + }, + "00013_00002-00095_00003" : { + "minimal_similarity" : 0.36046511627906974, + "maximum_similarity" : 0.6526315789473685, + "matched_token_number" : 62 + }, + "00194_00001-00196_00001" : { + "minimal_similarity" : 0.17034700315457413, + "maximum_similarity" : 0.5, + "matched_token_number" : 54 + }, + "00130_00002-00154_00002" : { + "minimal_similarity" : 0.5630252100840336, + "maximum_similarity" : 0.7701149425287356, + "matched_token_number" : 67 + }, + "00184_00002-00203_00002" : { + "minimal_similarity" : 0.45255474452554745, + "maximum_similarity" : 0.6595744680851063, + "matched_token_number" : 62 + }, + "00178_00002-00204_00001" : { + "minimal_similarity" : 0.5447154471544715, + "maximum_similarity" : 0.5583333333333333, + "matched_token_number" : 67 + }, + "00187_00001-00193_00001" : { + "minimal_similarity" : 0.6165413533834586, + "maximum_similarity" : 0.6212121212121212, + "matched_token_number" : 82 + }, + "00092_00001-00195_00001" : { + "minimal_similarity" : 0.5338983050847458, + "maximum_similarity" : 0.5338983050847458, + "matched_token_number" : 63 + }, + "00092_00001-00195_00002" : { + "minimal_similarity" : 0.5338983050847458, + "maximum_similarity" : 0.5338983050847458, + "matched_token_number" : 63 + }, + "00130_00002-00187_00001" : { + "minimal_similarity" : 0.44696969696969696, + "maximum_similarity" : 0.6781609195402298, + "matched_token_number" : 59 + }, + "00095_00003-00140_00001" : { + "minimal_similarity" : 0.25, + "maximum_similarity" : 0.4942528735632184, + "matched_token_number" : 43 + }, + "00077_00001-00125_00001" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00013_00002-00153_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.6421052631578947, + "matched_token_number" : 61 + }, + "00097_00002-00125_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5754716981132075, + "matched_token_number" : 61 + }, + "00095_00003-00147_00001" : { + "minimal_similarity" : 0.4127906976744186, + "maximum_similarity" : 0.6016949152542372, + "matched_token_number" : 71 + }, + "00014_00001-00160_00001" : { + "minimal_similarity" : 0.6029411764705882, + "maximum_similarity" : 0.7592592592592593, + "matched_token_number" : 82 + }, + "00013_00002-00186_00004" : { + "minimal_similarity" : 0.44339622641509435, + "maximum_similarity" : 0.49473684210526314, + "matched_token_number" : 47 + }, + "00147_00001-00201_00001" : { + "minimal_similarity" : 0.2966101694915254, + "maximum_similarity" : 0.40229885057471265, + "matched_token_number" : 35 + }, + "00196_00001-00197_00001" : { + "minimal_similarity" : 0.1861198738170347, + "maximum_similarity" : 0.44696969696969696, + "matched_token_number" : 59 + }, + "00136_00002-00197_00001" : { + "minimal_similarity" : 0.42777777777777776, + "maximum_similarity" : 0.5833333333333334, + "matched_token_number" : 77 + }, + "00121_00001-00196_00001" : { + "minimal_similarity" : 0.15141955835962145, + "maximum_similarity" : 0.35294117647058826, + "matched_token_number" : 48 + }, + "00013_00002-00186_00002" : { + "minimal_similarity" : 0.42028985507246375, + "maximum_similarity" : 0.6105263157894737, + "matched_token_number" : 58 + }, + "00000_00003-00136_00002" : { + "minimal_similarity" : 0.3055555555555556, + "maximum_similarity" : 0.46218487394957986, + "matched_token_number" : 55 + }, + "00044_00002-00133_00001" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.5656565656565656, + "matched_token_number" : 56 + }, + "00000_00002-00201_00001" : { + "minimal_similarity" : 0.2608695652173913, + "maximum_similarity" : 0.3448275862068966, + "matched_token_number" : 30 + }, + "00097_00002-00126_00002" : { + "minimal_similarity" : 0.4576271186440678, + "maximum_similarity" : 0.5094339622641509, + "matched_token_number" : 54 + }, + "00013_00002-00187_00001" : { + "minimal_similarity" : 0.4621212121212121, + "maximum_similarity" : 0.6421052631578947, + "matched_token_number" : 61 + }, + "00095_00003-00141_00002" : { + "minimal_similarity" : 0.313953488372093, + "maximum_similarity" : 0.5, + "matched_token_number" : 54 + }, + "00031_00003-00111_00001" : { + "minimal_similarity" : 0.43902439024390244, + "maximum_similarity" : 0.6352941176470588, + "matched_token_number" : 54 + }, + "00092_00001-00160_00001" : { + "minimal_similarity" : 0.45588235294117646, + "maximum_similarity" : 0.5254237288135594, + "matched_token_number" : 62 + }, + "00000_00003-00137_00002" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.47058823529411764, + "matched_token_number" : 56 + }, + "00031_00002-00129_00008" : { + "minimal_similarity" : 0.251063829787234, + "maximum_similarity" : 0.6413043478260869, + "matched_token_number" : 59 + }, + "00130_00002-00153_00001" : { + "minimal_similarity" : 0.5609756097560976, + "maximum_similarity" : 0.7931034482758621, + "matched_token_number" : 69 + }, + "00000_00002-00145_00001" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.48695652173913045, + "matched_token_number" : 56 + }, + "00000_00003-00135_00001" : { + "minimal_similarity" : 0.4178082191780822, + "maximum_similarity" : 0.5126050420168067, + "matched_token_number" : 61 + }, + "00195_00001-00195_00002" : { + "minimal_similarity" : 0.9830508474576272, + "maximum_similarity" : 0.9830508474576272, + "matched_token_number" : 116 + }, + "00000_00001-00155_00001" : { + "minimal_similarity" : 0.45918367346938777, + "maximum_similarity" : 0.5172413793103449, + "matched_token_number" : 45 + }, + "00111_00001-00120_00001" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00031_00002-00127_00002" : { + "minimal_similarity" : 0.4634146341463415, + "maximum_similarity" : 0.6195652173913043, + "matched_token_number" : 57 + }, + "00155_00001-00200_00002" : { + "minimal_similarity" : 0.4108527131782946, + "maximum_similarity" : 0.6091954022988506, + "matched_token_number" : 53 + }, + "00137_00002-00196_00001" : { + "minimal_similarity" : 0.17034700315457413, + "maximum_similarity" : 0.43902439024390244, + "matched_token_number" : 54 + }, + "00133_00001-00134_00001" : { + "minimal_similarity" : 0.4715447154471545, + "maximum_similarity" : 0.7160493827160493, + "matched_token_number" : 58 + }, + "00005_00002-00184_00002" : { + "minimal_similarity" : 0.4125, + "maximum_similarity" : 0.7021276595744681, + "matched_token_number" : 66 + }, + "00121_00001-00129_00008" : { + "minimal_similarity" : 0.35319148936170214, + "maximum_similarity" : 0.6102941176470589, + "matched_token_number" : 83 + }, + "00000_00002-00203_00002" : { + "minimal_similarity" : 0.4233576642335766, + "maximum_similarity" : 0.5043478260869565, + "matched_token_number" : 58 + }, + "00005_00002-00184_00003" : { + "minimal_similarity" : 0.4125, + "maximum_similarity" : 0.7021276595744681, + "matched_token_number" : 66 + }, + "00077_00001-00193_00001" : { + "minimal_similarity" : 0.44375, + "maximum_similarity" : 0.5338345864661654, + "matched_token_number" : 71 + }, + "00095_00003-00142_00001" : { + "minimal_similarity" : 0.36046511627906974, + "maximum_similarity" : 0.5254237288135594, + "matched_token_number" : 62 + }, + "00095_00003-00200_00002" : { + "minimal_similarity" : 0.3023255813953488, + "maximum_similarity" : 0.40310077519379844, + "matched_token_number" : 52 + }, + "00160_00001-00177_00003" : { + "minimal_similarity" : 0.6102941176470589, + "maximum_similarity" : 0.6747967479674797, + "matched_token_number" : 83 + }, + "00195_00001-00198_00001" : { + "minimal_similarity" : 0.3881578947368421, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00137_00002-00199_00001" : { + "minimal_similarity" : 0.5121951219512195, + "maximum_similarity" : 0.6631578947368421, + "matched_token_number" : 63 + }, + "00097_00002-00121_00001" : { + "minimal_similarity" : 0.4852941176470588, + "maximum_similarity" : 0.6226415094339622, + "matched_token_number" : 66 + }, + "00005_00002-00187_00001" : { + "minimal_similarity" : 0.49375, + "maximum_similarity" : 0.5984848484848485, + "matched_token_number" : 79 + }, + "00196_00001-00198_00001" : { + "minimal_similarity" : 0.1892744479495268, + "maximum_similarity" : 0.39473684210526316, + "matched_token_number" : 60 + }, + "00120_00001-00127_00002" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00092_00001-00196_00001" : { + "minimal_similarity" : 0.14826498422712933, + "maximum_similarity" : 0.3983050847457627, + "matched_token_number" : 47 + }, + "00120_00001-00129_00008" : { + "minimal_similarity" : 0.2723404255319149, + "maximum_similarity" : 0.5423728813559322, + "matched_token_number" : 64 + }, + "00013_00002-00092_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5894736842105263, + "matched_token_number" : 56 + }, + "00044_00002-00131_00005" : { + "minimal_similarity" : 0.3625, + "maximum_similarity" : 0.5858585858585859, + "matched_token_number" : 58 + }, + "00000_00001-00097_00002" : { + "minimal_similarity" : 0.42452830188679247, + "maximum_similarity" : 0.45918367346938777, + "matched_token_number" : 45 + }, + "00186_00004-00194_00001" : { + "minimal_similarity" : 0.49074074074074076, + "maximum_similarity" : 0.5, + "matched_token_number" : 53 + }, + "00134_00001-00137_00002" : { + "minimal_similarity" : 0.4715447154471545, + "maximum_similarity" : 0.7160493827160493, + "matched_token_number" : 58 + }, + "00000_00003-00077_00001" : { + "minimal_similarity" : 0.40625, + "maximum_similarity" : 0.5462184873949579, + "matched_token_number" : 65 + }, + "00186_00004-00192_00002" : { + "minimal_similarity" : 0.5114503816793893, + "maximum_similarity" : 0.6320754716981132, + "matched_token_number" : 67 + }, + "00186_00004-00192_00001" : { + "minimal_similarity" : 0.4258064516129032, + "maximum_similarity" : 0.6226415094339622, + "matched_token_number" : 66 + }, + "00155_00001-00202_00002" : { + "minimal_similarity" : 0.375886524822695, + "maximum_similarity" : 0.6091954022988506, + "matched_token_number" : 53 + }, + "00155_00001-00202_00003" : { + "minimal_similarity" : 0.3829787234042553, + "maximum_similarity" : 0.6206896551724138, + "matched_token_number" : 54 + }, + "00121_00001-00193_00001" : { + "minimal_similarity" : 0.5588235294117647, + "maximum_similarity" : 0.5714285714285714, + "matched_token_number" : 76 + }, + "00077_00001-00129_00008" : { + "minimal_similarity" : 0.3021276595744681, + "maximum_similarity" : 0.44375, + "matched_token_number" : 71 + }, + "00005_00002-00186_00004" : { + "minimal_similarity" : 0.39375, + "maximum_similarity" : 0.5943396226415094, + "matched_token_number" : 63 + }, + "00092_00001-00199_00001" : { + "minimal_similarity" : 0.3898305084745763, + "maximum_similarity" : 0.4842105263157895, + "matched_token_number" : 46 + }, + "00137_00002-00198_00001" : { + "minimal_similarity" : 0.4342105263157895, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00005_00002-00186_00002" : { + "minimal_similarity" : 0.4125, + "maximum_similarity" : 0.4782608695652174, + "matched_token_number" : 66 + }, + "00077_00001-00192_00001" : { + "minimal_similarity" : 0.55, + "maximum_similarity" : 0.567741935483871, + "matched_token_number" : 88 + }, + "00136_00002-00194_00001" : { + "minimal_similarity" : 0.35555555555555557, + "maximum_similarity" : 0.5925925925925926, + "matched_token_number" : 64 + }, + "00077_00001-00192_00002" : { + "minimal_similarity" : 0.5375, + "maximum_similarity" : 0.6564885496183206, + "matched_token_number" : 86 + }, + "00095_00003-00202_00002" : { + "minimal_similarity" : 0.3953488372093023, + "maximum_similarity" : 0.48226950354609927, + "matched_token_number" : 68 + }, + "00000_00003-00133_00001" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.47058823529411764, + "matched_token_number" : 56 + }, + "00095_00003-00202_00003" : { + "minimal_similarity" : 0.3953488372093023, + "maximum_similarity" : 0.48226950354609927, + "matched_token_number" : 68 + }, + "00135_00001-00138_00001" : { + "minimal_similarity" : 0.4452054794520548, + "maximum_similarity" : 0.5508474576271186, + "matched_token_number" : 65 + }, + "00134_00001-00136_00002" : { + "minimal_similarity" : 0.2611111111111111, + "maximum_similarity" : 0.5802469135802469, + "matched_token_number" : 47 + }, + "00031_00002-00125_00001" : { + "minimal_similarity" : 0.4634146341463415, + "maximum_similarity" : 0.6195652173913043, + "matched_token_number" : 57 + }, + "00155_00001-00203_00002" : { + "minimal_similarity" : 0.40145985401459855, + "maximum_similarity" : 0.632183908045977, + "matched_token_number" : 55 + }, + "00092_00001-00198_00001" : { + "minimal_similarity" : 0.5131578947368421, + "maximum_similarity" : 0.6610169491525424, + "matched_token_number" : 78 + }, + "00121_00001-00194_00001" : { + "minimal_similarity" : 0.49264705882352944, + "maximum_similarity" : 0.6203703703703703, + "matched_token_number" : 67 + }, + "00095_00003-00145_00001" : { + "minimal_similarity" : 0.42441860465116277, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00000_00003-00134_00001" : { + "minimal_similarity" : 0.35294117647058826, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 42 + }, + "00186_00004-00193_00001" : { + "minimal_similarity" : 0.45112781954887216, + "maximum_similarity" : 0.5660377358490566, + "matched_token_number" : 60 + }, + "00095_00003-00203_00002" : { + "minimal_similarity" : 0.36627906976744184, + "maximum_similarity" : 0.45985401459854014, + "matched_token_number" : 63 + }, + "00195_00001-00196_00001" : { + "minimal_similarity" : 0.17981072555205047, + "maximum_similarity" : 0.4830508474576271, + "matched_token_number" : 57 + }, + "00137_00002-00197_00001" : { + "minimal_similarity" : 0.5909090909090909, + "maximum_similarity" : 0.6341463414634146, + "matched_token_number" : 78 + }, + "00000_00002-00204_00001" : { + "minimal_similarity" : 0.4166666666666667, + "maximum_similarity" : 0.43478260869565216, + "matched_token_number" : 50 + }, + "00153_00001-00178_00002" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00031_00002-00126_00002" : { + "minimal_similarity" : 0.4322033898305085, + "maximum_similarity" : 0.5543478260869565, + "matched_token_number" : 51 + }, + "00136_00002-00193_00001" : { + "minimal_similarity" : 0.45, + "maximum_similarity" : 0.6090225563909775, + "matched_token_number" : 81 + }, + "00134_00001-00155_00001" : { + "minimal_similarity" : 0.7241379310344828, + "maximum_similarity" : 0.7777777777777778, + "matched_token_number" : 63 + }, + "00130_00002-00201_00001" : { + "minimal_similarity" : 0.41379310344827586, + "maximum_similarity" : 0.41379310344827586, + "matched_token_number" : 36 + }, + "00121_00001-00145_00001" : { + "minimal_similarity" : 0.6985294117647058, + "maximum_similarity" : 0.7723577235772358, + "matched_token_number" : 95 + }, + "00000_00001-00119_00001" : { + "minimal_similarity" : 0.5277777777777778, + "maximum_similarity" : 0.5816326530612245, + "matched_token_number" : 57 + }, + "00140_00001-00141_00002" : { + "minimal_similarity" : 0.46296296296296297, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00131_00005-00136_00002" : { + "minimal_similarity" : 0.4722222222222222, + "maximum_similarity" : 0.53125, + "matched_token_number" : 85 + }, + "00113_00002-00154_00002" : { + "minimal_similarity" : 0.8852459016393442, + "maximum_similarity" : 0.907563025210084, + "matched_token_number" : 108 + }, + "00000_00003-00119_00001" : { + "minimal_similarity" : 0.4957983193277311, + "maximum_similarity" : 0.5462962962962963, + "matched_token_number" : 59 + }, + "00000_00005-00119_00001" : { + "minimal_similarity" : 0.4666666666666667, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 56 + }, + "00044_00002-00183_00004" : { + "minimal_similarity" : 0.3971631205673759, + "maximum_similarity" : 0.5656565656565656, + "matched_token_number" : 56 + }, + "00092_00001-00184_00002" : { + "minimal_similarity" : 0.3983050847457627, + "maximum_similarity" : 0.5, + "matched_token_number" : 47 + }, + "00092_00001-00184_00003" : { + "minimal_similarity" : 0.3983050847457627, + "maximum_similarity" : 0.5, + "matched_token_number" : 47 + }, + "00202_00003-00204_00001" : { + "minimal_similarity" : 0.624113475177305, + "maximum_similarity" : 0.7333333333333333, + "matched_token_number" : 88 + }, + "00129_00008-00183_00004" : { + "minimal_similarity" : 0.37872340425531914, + "maximum_similarity" : 0.6312056737588653, + "matched_token_number" : 89 + }, + "00127_00002-00129_00008" : { + "minimal_similarity" : 0.3191489361702128, + "maximum_similarity" : 0.6097560975609756, + "matched_token_number" : 75 + }, + "00197_00001-00204_00001" : { + "minimal_similarity" : 0.7196969696969697, + "maximum_similarity" : 0.7916666666666666, + "matched_token_number" : 95 + }, + "00031_00003-00160_00001" : { + "minimal_similarity" : 0.3897058823529412, + "maximum_similarity" : 0.6235294117647059, + "matched_token_number" : 53 + }, + "00153_00001-00177_00003" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00145_00001-00178_00002" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00031_00003-00203_00002" : { + "minimal_similarity" : 0.4233576642335766, + "maximum_similarity" : 0.6823529411764706, + "matched_token_number" : 58 + }, + "00013_00002-00111_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.6421052631578947, + "matched_token_number" : 61 + }, + "00077_00001-00141_00002" : { + "minimal_similarity" : 0.3375, + "maximum_similarity" : 0.5, + "matched_token_number" : 54 + }, + "00156_00002-00183_00004" : { + "minimal_similarity" : 0.48226950354609927, + "maximum_similarity" : 0.5, + "matched_token_number" : 68 + }, + "00136_00002-00155_00001" : { + "minimal_similarity" : 0.29444444444444445, + "maximum_similarity" : 0.6091954022988506, + "matched_token_number" : 53 + }, + "00137_00002-00187_00001" : { + "minimal_similarity" : 0.5909090909090909, + "maximum_similarity" : 0.6341463414634146, + "matched_token_number" : 78 + }, + "00097_00002-00136_00002" : { + "minimal_similarity" : 0.35555555555555557, + "maximum_similarity" : 0.6037735849056604, + "matched_token_number" : 64 + }, + "00000_00002-00199_00001" : { + "minimal_similarity" : 0.5130434782608696, + "maximum_similarity" : 0.6210526315789474, + "matched_token_number" : 59 + }, + "00160_00001-00195_00002" : { + "minimal_similarity" : 0.47058823529411764, + "maximum_similarity" : 0.5423728813559322, + "matched_token_number" : 64 + }, + "00160_00001-00195_00001" : { + "minimal_similarity" : 0.47058823529411764, + "maximum_similarity" : 0.5423728813559322, + "matched_token_number" : 64 + }, + "00031_00002-00199_00001" : { + "minimal_similarity" : 0.5157894736842106, + "maximum_similarity" : 0.532608695652174, + "matched_token_number" : 49 + }, + "00195_00002-00204_00001" : { + "minimal_similarity" : 0.4666666666666667, + "maximum_similarity" : 0.4745762711864407, + "matched_token_number" : 56 + }, + "00125_00001-00129_00008" : { + "minimal_similarity" : 0.3191489361702128, + "maximum_similarity" : 0.6097560975609756, + "matched_token_number" : 75 + }, + "00147_00001-00160_00001" : { + "minimal_similarity" : 0.45588235294117646, + "maximum_similarity" : 0.5254237288135594, + "matched_token_number" : 62 + }, + "00000_00002-00127_00002" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.48695652173913045, + "matched_token_number" : 56 + }, + "00095_00003-00131_00005" : { + "minimal_similarity" : 0.37790697674418605, + "maximum_similarity" : 0.40625, + "matched_token_number" : 65 + }, + "00005_00002-00138_00001" : { + "minimal_similarity" : 0.45625, + "maximum_similarity" : 0.6186440677966102, + "matched_token_number" : 73 + }, + "00135_00001-00187_00001" : { + "minimal_similarity" : 0.4931506849315068, + "maximum_similarity" : 0.5454545454545454, + "matched_token_number" : 72 + }, + "00200_00002-00204_00001" : { + "minimal_similarity" : 0.5426356589147286, + "maximum_similarity" : 0.5833333333333334, + "matched_token_number" : 70 + }, + "00121_00001-00140_00001" : { + "minimal_similarity" : 0.4632352941176471, + "maximum_similarity" : 0.7241379310344828, + "matched_token_number" : 63 + }, + "00000_00001-00160_00001" : { + "minimal_similarity" : 0.4632352941176471, + "maximum_similarity" : 0.6428571428571429, + "matched_token_number" : 63 + }, + "00000_00003-00160_00001" : { + "minimal_similarity" : 0.4632352941176471, + "maximum_similarity" : 0.5294117647058824, + "matched_token_number" : 63 + }, + "00193_00001-00204_00001" : { + "minimal_similarity" : 0.5864661654135338, + "maximum_similarity" : 0.65, + "matched_token_number" : 78 + }, + "00077_00001-00200_00002" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6511627906976745, + "matched_token_number" : 84 + }, + "00141_00002-00186_00004" : { + "minimal_similarity" : 0.49074074074074076, + "maximum_similarity" : 0.5, + "matched_token_number" : 53 + }, + "00154_00002-00196_00001" : { + "minimal_similarity" : 0.1608832807570978, + "maximum_similarity" : 0.42857142857142855, + "matched_token_number" : 51 + }, + "00141_00002-00186_00002" : { + "minimal_similarity" : 0.39855072463768115, + "maximum_similarity" : 0.5092592592592593, + "matched_token_number" : 55 + }, + "00014_00001-00092_00001" : { + "minimal_similarity" : 0.4152542372881356, + "maximum_similarity" : 0.4537037037037037, + "matched_token_number" : 49 + }, + "00140_00001-00200_00002" : { + "minimal_similarity" : 0.43410852713178294, + "maximum_similarity" : 0.6436781609195402, + "matched_token_number" : 56 + }, + "00031_00003-00186_00002" : { + "minimal_similarity" : 0.4057971014492754, + "maximum_similarity" : 0.6588235294117647, + "matched_token_number" : 56 + }, + "00126_00002-00202_00002" : { + "minimal_similarity" : 0.4326241134751773, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00000_00002-00194_00001" : { + "minimal_similarity" : 0.4782608695652174, + "maximum_similarity" : 0.5092592592592593, + "matched_token_number" : 55 + }, + "00126_00002-00202_00003" : { + "minimal_similarity" : 0.41843971631205673, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00129_00008-00137_00002" : { + "minimal_similarity" : 0.3191489361702128, + "maximum_similarity" : 0.6097560975609756, + "matched_token_number" : 75 + }, + "00121_00001-00204_00001" : { + "minimal_similarity" : 0.5441176470588235, + "maximum_similarity" : 0.6166666666666667, + "matched_token_number" : 74 + }, + "00184_00002-00202_00002" : { + "minimal_similarity" : 0.425531914893617, + "maximum_similarity" : 0.6382978723404256, + "matched_token_number" : 60 + }, + "00184_00002-00202_00003" : { + "minimal_similarity" : 0.4397163120567376, + "maximum_similarity" : 0.6595744680851063, + "matched_token_number" : 62 + }, + "00129_00008-00200_00002" : { + "minimal_similarity" : 0.2680851063829787, + "maximum_similarity" : 0.4883720930232558, + "matched_token_number" : 63 + }, + "00097_00002-00131_00005" : { + "minimal_similarity" : 0.3, + "maximum_similarity" : 0.4528301886792453, + "matched_token_number" : 48 + }, + "00031_00003-00186_00004" : { + "minimal_similarity" : 0.5566037735849056, + "maximum_similarity" : 0.6941176470588235, + "matched_token_number" : 59 + }, + "00145_00001-00199_00001" : { + "minimal_similarity" : 0.5121951219512195, + "maximum_similarity" : 0.6631578947368421, + "matched_token_number" : 63 + }, + "00142_00001-00154_00002" : { + "minimal_similarity" : 0.5294117647058824, + "maximum_similarity" : 0.5338983050847458, + "matched_token_number" : 63 + }, + "00092_00001-00201_00001" : { + "minimal_similarity" : 0.2966101694915254, + "maximum_similarity" : 0.40229885057471265, + "matched_token_number" : 35 + }, + "00135_00001-00136_00002" : { + "minimal_similarity" : 0.48333333333333334, + "maximum_similarity" : 0.5958904109589042, + "matched_token_number" : 87 + }, + "00005_00002-00095_00003" : { + "minimal_similarity" : 0.37790697674418605, + "maximum_similarity" : 0.40625, + "matched_token_number" : 65 + }, + "00119_00001-00138_00001" : { + "minimal_similarity" : 0.4152542372881356, + "maximum_similarity" : 0.4537037037037037, + "matched_token_number" : 49 + }, + "00014_00001-00156_00003" : { + "minimal_similarity" : 0.5220588235294118, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00153_00001-00198_00001" : { + "minimal_similarity" : 0.4342105263157895, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00014_00001-00156_00002" : { + "minimal_similarity" : 0.5220588235294118, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00092_00001-00138_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 118 + }, + "00095_00003-00136_00002" : { + "minimal_similarity" : 0.4222222222222222, + "maximum_similarity" : 0.4418604651162791, + "matched_token_number" : 76 + }, + "00156_00003-00196_00001" : { + "minimal_similarity" : 0.25236593059936907, + "maximum_similarity" : 0.5882352941176471, + "matched_token_number" : 80 + }, + "00141_00002-00203_00002" : { + "minimal_similarity" : 0.48905109489051096, + "maximum_similarity" : 0.6203703703703703, + "matched_token_number" : 67 + }, + "00044_00002-00137_00002" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.5656565656565656, + "matched_token_number" : 56 + }, + "00177_00003-00201_00001" : { + "minimal_similarity" : 0.3008130081300813, + "maximum_similarity" : 0.42528735632183906, + "matched_token_number" : 37 + }, + "00000_00003-00203_00002" : { + "minimal_similarity" : 0.45985401459854014, + "maximum_similarity" : 0.5294117647058824, + "matched_token_number" : 63 + }, + "00119_00001-00184_00003" : { + "minimal_similarity" : 0.5092592592592593, + "maximum_similarity" : 0.5851063829787234, + "matched_token_number" : 55 + }, + "00111_00001-00133_00001" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00119_00001-00184_00002" : { + "minimal_similarity" : 0.5092592592592593, + "maximum_similarity" : 0.5851063829787234, + "matched_token_number" : 55 + }, + "00000_00001-00203_00002" : { + "minimal_similarity" : 0.40875912408759124, + "maximum_similarity" : 0.5714285714285714, + "matched_token_number" : 56 + }, + "00000_00002-00178_00002" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.48695652173913045, + "matched_token_number" : 56 + }, + "00014_00001-00097_00002" : { + "minimal_similarity" : 0.5833333333333334, + "maximum_similarity" : 0.5943396226415094, + "matched_token_number" : 63 + }, + "00125_00001-00140_00001" : { + "minimal_similarity" : 0.5609756097560976, + "maximum_similarity" : 0.7931034482758621, + "matched_token_number" : 69 + }, + "00077_00001-00120_00001" : { + "minimal_similarity" : 0.46875, + "maximum_similarity" : 0.635593220338983, + "matched_token_number" : 75 + }, + "00120_00001-00202_00003" : { + "minimal_similarity" : 0.41843971631205673, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00014_00001-00198_00001" : { + "minimal_similarity" : 0.3618421052631579, + "maximum_similarity" : 0.5092592592592593, + "matched_token_number" : 55 + }, + "00120_00001-00202_00002" : { + "minimal_similarity" : 0.4326241134751773, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00095_00003-00178_00002" : { + "minimal_similarity" : 0.42441860465116277, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00005_00002-00201_00001" : { + "minimal_similarity" : 0.24375, + "maximum_similarity" : 0.4482758620689655, + "matched_token_number" : 39 + }, + "00097_00002-00187_00001" : { + "minimal_similarity" : 0.42424242424242425, + "maximum_similarity" : 0.5283018867924528, + "matched_token_number" : 56 + }, + "00044_00002-00111_00001" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.5656565656565656, + "matched_token_number" : 56 + }, + "00134_00001-00197_00001" : { + "minimal_similarity" : 0.36363636363636365, + "maximum_similarity" : 0.5925925925925926, + "matched_token_number" : 48 + }, + "00113_00002-00133_00001" : { + "minimal_similarity" : 0.943089430894309, + "maximum_similarity" : 0.9508196721311475, + "matched_token_number" : 116 + }, + "00137_00002-00140_00001" : { + "minimal_similarity" : 0.5609756097560976, + "maximum_similarity" : 0.7931034482758621, + "matched_token_number" : 69 + }, + "00131_00005-00178_00002" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00092_00001-00133_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00119_00001-00133_00001" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00153_00001-00193_00001" : { + "minimal_similarity" : 0.5488721804511278, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00031_00003-00119_00001" : { + "minimal_similarity" : 0.5092592592592593, + "maximum_similarity" : 0.6470588235294118, + "matched_token_number" : 55 + }, + "00130_00002-00184_00003" : { + "minimal_similarity" : 0.46808510638297873, + "maximum_similarity" : 0.5057471264367817, + "matched_token_number" : 44 + }, + "00130_00002-00184_00002" : { + "minimal_similarity" : 0.46808510638297873, + "maximum_similarity" : 0.5057471264367817, + "matched_token_number" : 44 + }, + "00187_00001-00196_00001" : { + "minimal_similarity" : 0.1861198738170347, + "maximum_similarity" : 0.44696969696969696, + "matched_token_number" : 59 + }, + "00127_00002-00140_00001" : { + "minimal_similarity" : 0.5609756097560976, + "maximum_similarity" : 0.7931034482758621, + "matched_token_number" : 69 + }, + "00013_00002-00183_00004" : { + "minimal_similarity" : 0.3829787234042553, + "maximum_similarity" : 0.5684210526315789, + "matched_token_number" : 54 + }, + "00014_00001-00177_00003" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00031_00003-00097_00002" : { + "minimal_similarity" : 0.42452830188679247, + "maximum_similarity" : 0.5294117647058824, + "matched_token_number" : 45 + }, + "00044_00002-00200_00002" : { + "minimal_similarity" : 0.3875968992248062, + "maximum_similarity" : 0.5050505050505051, + "matched_token_number" : 50 + }, + "00014_00001-00130_00002" : { + "minimal_similarity" : 0.46296296296296297, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00138_00001-00155_00001" : { + "minimal_similarity" : 0.3220338983050847, + "maximum_similarity" : 0.4367816091954023, + "matched_token_number" : 38 + }, + "00192_00002-00198_00001" : { + "minimal_similarity" : 0.5197368421052632, + "maximum_similarity" : 0.6030534351145038, + "matched_token_number" : 79 + }, + "00000_00005-00092_00001" : { + "minimal_similarity" : 0.38333333333333336, + "maximum_similarity" : 0.3898305084745763, + "matched_token_number" : 46 + }, + "00178_00002-00194_00001" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00044_00002-00141_00002" : { + "minimal_similarity" : 0.4537037037037037, + "maximum_similarity" : 0.494949494949495, + "matched_token_number" : 49 + }, + "00111_00001-00154_00002" : { + "minimal_similarity" : 0.8780487804878049, + "maximum_similarity" : 0.907563025210084, + "matched_token_number" : 108 + }, + "00133_00001-00195_00001" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00133_00001-00195_00002" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00147_00001-00203_00002" : { + "minimal_similarity" : 0.46715328467153283, + "maximum_similarity" : 0.5423728813559322, + "matched_token_number" : 64 + }, + "00184_00003-00198_00001" : { + "minimal_similarity" : 0.40789473684210525, + "maximum_similarity" : 0.6595744680851063, + "matched_token_number" : 62 + }, + "00000_00001-00092_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5714285714285714, + "matched_token_number" : 56 + }, + "00194_00001-00198_00001" : { + "minimal_similarity" : 0.3618421052631579, + "maximum_similarity" : 0.5092592592592593, + "matched_token_number" : 55 + }, + "00160_00001-00203_00002" : { + "minimal_similarity" : 0.5693430656934306, + "maximum_similarity" : 0.5735294117647058, + "matched_token_number" : 78 + }, + "00031_00002-00194_00001" : { + "minimal_similarity" : 0.5185185185185185, + "maximum_similarity" : 0.6086956521739131, + "matched_token_number" : 56 + }, + "00000_00005-00203_00002" : { + "minimal_similarity" : 0.4744525547445255, + "maximum_similarity" : 0.5416666666666666, + "matched_token_number" : 65 + }, + "00014_00001-00119_00001" : { + "minimal_similarity" : 0.9722222222222222, + "maximum_similarity" : 0.9722222222222222, + "matched_token_number" : 105 + }, + "00000_00003-00092_00001" : { + "minimal_similarity" : 0.40336134453781514, + "maximum_similarity" : 0.4067796610169492, + "matched_token_number" : 48 + }, + "00130_00002-00133_00001" : { + "minimal_similarity" : 0.5609756097560976, + "maximum_similarity" : 0.7931034482758621, + "matched_token_number" : 69 + }, + "00097_00002-00140_00001" : { + "minimal_similarity" : 0.42452830188679247, + "maximum_similarity" : 0.5172413793103449, + "matched_token_number" : 45 + }, + "00014_00001-00126_00002" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 56 + }, + "00138_00001-00197_00001" : { + "minimal_similarity" : 0.48484848484848486, + "maximum_similarity" : 0.5423728813559322, + "matched_token_number" : 64 + }, + "00113_00002-00184_00002" : { + "minimal_similarity" : 0.5245901639344263, + "maximum_similarity" : 0.6808510638297872, + "matched_token_number" : 64 + }, + "00031_00003-00092_00001" : { + "minimal_similarity" : 0.4067796610169492, + "maximum_similarity" : 0.5647058823529412, + "matched_token_number" : 48 + }, + "00113_00002-00184_00003" : { + "minimal_similarity" : 0.5245901639344263, + "maximum_similarity" : 0.6808510638297872, + "matched_token_number" : 64 + }, + "00126_00002-00194_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 56 + }, + "00125_00001-00187_00001" : { + "minimal_similarity" : 0.5909090909090909, + "maximum_similarity" : 0.6341463414634146, + "matched_token_number" : 78 + }, + "00092_00001-00121_00001" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00127_00002-00204_00001" : { + "minimal_similarity" : 0.5447154471544715, + "maximum_similarity" : 0.5583333333333333, + "matched_token_number" : 67 + }, + "00000_00005-00013_00002" : { + "minimal_similarity" : 0.36666666666666664, + "maximum_similarity" : 0.4631578947368421, + "matched_token_number" : 44 + }, + "00131_00005-00199_00001" : { + "minimal_similarity" : 0.41875, + "maximum_similarity" : 0.7052631578947368, + "matched_token_number" : 67 + }, + "00126_00002-00134_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.691358024691358, + "matched_token_number" : 56 + }, + "00140_00001-00197_00001" : { + "minimal_similarity" : 0.44696969696969696, + "maximum_similarity" : 0.6781609195402298, + "matched_token_number" : 59 + }, + "00000_00001-00013_00002" : { + "minimal_similarity" : 0.4489795918367347, + "maximum_similarity" : 0.4631578947368421, + "matched_token_number" : 44 + }, + "00135_00001-00178_00002" : { + "minimal_similarity" : 0.5273972602739726, + "maximum_similarity" : 0.6260162601626016, + "matched_token_number" : 77 + }, + "00186_00002-00198_00001" : { + "minimal_similarity" : 0.5131578947368421, + "maximum_similarity" : 0.5652173913043478, + "matched_token_number" : 78 + }, + "00201_00001-00202_00002" : { + "minimal_similarity" : 0.3120567375886525, + "maximum_similarity" : 0.5057471264367817, + "matched_token_number" : 44 + }, + "00131_00005-00204_00001" : { + "minimal_similarity" : 0.5125, + "maximum_similarity" : 0.6833333333333333, + "matched_token_number" : 82 + }, + "00154_00002-00204_00001" : { + "minimal_similarity" : 0.5333333333333333, + "maximum_similarity" : 0.5378151260504201, + "matched_token_number" : 64 + }, + "00120_00001-00155_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.6436781609195402, + "matched_token_number" : 56 + }, + "00119_00001-00142_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 56 + }, + "00097_00002-00199_00001" : { + "minimal_similarity" : 0.49056603773584906, + "maximum_similarity" : 0.5473684210526316, + "matched_token_number" : 52 + }, + "00199_00001-00200_00002" : { + "minimal_similarity" : 0.4263565891472868, + "maximum_similarity" : 0.5789473684210527, + "matched_token_number" : 55 + }, + "00192_00001-00192_00002" : { + "minimal_similarity" : 0.7483870967741936, + "maximum_similarity" : 0.8854961832061069, + "matched_token_number" : 116 + }, + "00111_00001-00184_00002" : { + "minimal_similarity" : 0.5203252032520326, + "maximum_similarity" : 0.6808510638297872, + "matched_token_number" : 64 + }, + "00111_00001-00184_00003" : { + "minimal_similarity" : 0.5203252032520326, + "maximum_similarity" : 0.6808510638297872, + "matched_token_number" : 64 + }, + "00133_00001-00153_00001" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00127_00002-00187_00001" : { + "minimal_similarity" : 0.5909090909090909, + "maximum_similarity" : 0.6341463414634146, + "matched_token_number" : 78 + }, + "00186_00002-00186_00004" : { + "minimal_similarity" : 0.4927536231884058, + "maximum_similarity" : 0.6415094339622641, + "matched_token_number" : 68 + }, + "00138_00001-00202_00003" : { + "minimal_similarity" : 0.40425531914893614, + "maximum_similarity" : 0.4830508474576271, + "matched_token_number" : 57 + }, + "00014_00001-00186_00002" : { + "minimal_similarity" : 0.39855072463768115, + "maximum_similarity" : 0.5092592592592593, + "matched_token_number" : 55 + }, + "00138_00001-00202_00002" : { + "minimal_similarity" : 0.40425531914893614, + "maximum_similarity" : 0.4830508474576271, + "matched_token_number" : 57 + }, + "00156_00003-00204_00001" : { + "minimal_similarity" : 0.4852941176470588, + "maximum_similarity" : 0.55, + "matched_token_number" : 66 + }, + "00192_00001-00202_00002" : { + "minimal_similarity" : 0.7548387096774194, + "maximum_similarity" : 0.8297872340425532, + "matched_token_number" : 117 + }, + "00192_00001-00202_00003" : { + "minimal_similarity" : 0.7741935483870968, + "maximum_similarity" : 0.851063829787234, + "matched_token_number" : 120 + }, + "00014_00001-00186_00004" : { + "minimal_similarity" : 0.49074074074074076, + "maximum_similarity" : 0.5, + "matched_token_number" : 53 + }, + "00178_00002-00187_00001" : { + "minimal_similarity" : 0.5909090909090909, + "maximum_similarity" : 0.6341463414634146, + "matched_token_number" : 78 + }, + "00133_00001-00203_00002" : { + "minimal_similarity" : 0.5766423357664233, + "maximum_similarity" : 0.6422764227642277, + "matched_token_number" : 79 + }, + "00125_00001-00154_00002" : { + "minimal_similarity" : 0.8780487804878049, + "maximum_similarity" : 0.907563025210084, + "matched_token_number" : 108 + }, + "00142_00001-00184_00002" : { + "minimal_similarity" : 0.4661016949152542, + "maximum_similarity" : 0.5851063829787234, + "matched_token_number" : 55 + }, + "00142_00001-00184_00003" : { + "minimal_similarity" : 0.4661016949152542, + "maximum_similarity" : 0.5851063829787234, + "matched_token_number" : 55 + }, + "00131_00005-00140_00001" : { + "minimal_similarity" : 0.3375, + "maximum_similarity" : 0.6206896551724138, + "matched_token_number" : 54 + }, + "00125_00001-00204_00001" : { + "minimal_similarity" : 0.5447154471544715, + "maximum_similarity" : 0.5583333333333333, + "matched_token_number" : 67 + }, + "00111_00001-00145_00001" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00138_00001-00192_00002" : { + "minimal_similarity" : 0.44274809160305345, + "maximum_similarity" : 0.4915254237288136, + "matched_token_number" : 58 + }, + "00000_00001-00130_00002" : { + "minimal_similarity" : 0.5204081632653061, + "maximum_similarity" : 0.5862068965517241, + "matched_token_number" : 51 + }, + "00119_00001-00196_00001" : { + "minimal_similarity" : 0.17034700315457413, + "maximum_similarity" : 0.5, + "matched_token_number" : 54 + }, + "00092_00001-00126_00002" : { + "minimal_similarity" : 0.5338983050847458, + "maximum_similarity" : 0.5338983050847458, + "matched_token_number" : 63 + }, + "00138_00001-00192_00001" : { + "minimal_similarity" : 0.38064516129032255, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00129_00008-00141_00002" : { + "minimal_similarity" : 0.2978723404255319, + "maximum_similarity" : 0.6481481481481481, + "matched_token_number" : 70 + }, + "00141_00002-00156_00003" : { + "minimal_similarity" : 0.5220588235294118, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00000_00002-00005_00002" : { + "minimal_similarity" : 0.39375, + "maximum_similarity" : 0.5478260869565217, + "matched_token_number" : 63 + }, + "00141_00002-00156_00002" : { + "minimal_similarity" : 0.5220588235294118, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00014_00001-00203_00002" : { + "minimal_similarity" : 0.48905109489051096, + "maximum_similarity" : 0.6203703703703703, + "matched_token_number" : 67 + }, + "00031_00003-00135_00001" : { + "minimal_similarity" : 0.3835616438356164, + "maximum_similarity" : 0.6588235294117647, + "matched_token_number" : 56 + }, + "00111_00001-00129_00008" : { + "minimal_similarity" : 0.3191489361702128, + "maximum_similarity" : 0.6097560975609756, + "matched_token_number" : 75 + }, + "00126_00002-00127_00002" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00005_00002-00147_00001" : { + "minimal_similarity" : 0.45625, + "maximum_similarity" : 0.6186440677966102, + "matched_token_number" : 73 + }, + "00201_00001-00202_00003" : { + "minimal_similarity" : 0.3120567375886525, + "maximum_similarity" : 0.5057471264367817, + "matched_token_number" : 44 + }, + "00005_00002-00044_00002" : { + "minimal_similarity" : 0.3625, + "maximum_similarity" : 0.5858585858585859, + "matched_token_number" : 58 + }, + "00113_00002-00129_00008" : { + "minimal_similarity" : 0.3191489361702128, + "maximum_similarity" : 0.6147540983606558, + "matched_token_number" : 75 + }, + "00097_00002-00194_00001" : { + "minimal_similarity" : 0.5833333333333334, + "maximum_similarity" : 0.5943396226415094, + "matched_token_number" : 63 + }, + "00000_00002-00131_00005" : { + "minimal_similarity" : 0.39375, + "maximum_similarity" : 0.5478260869565217, + "matched_token_number" : 63 + }, + "00127_00002-00154_00002" : { + "minimal_similarity" : 0.8780487804878049, + "maximum_similarity" : 0.907563025210084, + "matched_token_number" : 108 + }, + "00192_00002-00201_00001" : { + "minimal_similarity" : 0.3816793893129771, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00119_00001-00154_00002" : { + "minimal_similarity" : 0.5714285714285714, + "maximum_similarity" : 0.6296296296296297, + "matched_token_number" : 68 + }, + "00186_00002-00203_00002" : { + "minimal_similarity" : 0.6304347826086957, + "maximum_similarity" : 0.635036496350365, + "matched_token_number" : 87 + }, + "00000_00005-00177_00003" : { + "minimal_similarity" : 0.4634146341463415, + "maximum_similarity" : 0.475, + "matched_token_number" : 57 + }, + "00131_00005-00145_00001" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00119_00001-00201_00001" : { + "minimal_similarity" : 0.37037037037037035, + "maximum_similarity" : 0.45977011494252873, + "matched_token_number" : 40 + }, + "00000_00005-00130_00002" : { + "minimal_similarity" : 0.4166666666666667, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00000_00001-00177_00003" : { + "minimal_similarity" : 0.43902439024390244, + "maximum_similarity" : 0.5510204081632653, + "matched_token_number" : 54 + }, + "00192_00002-00193_00001" : { + "minimal_similarity" : 0.6541353383458647, + "maximum_similarity" : 0.6641221374045801, + "matched_token_number" : 87 + }, + "00113_00002-00138_00001" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00183_00004-00192_00001" : { + "minimal_similarity" : 0.6, + "maximum_similarity" : 0.6595744680851063, + "matched_token_number" : 93 + }, + "00145_00001-00202_00002" : { + "minimal_similarity" : 0.46808510638297873, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00183_00004-00192_00002" : { + "minimal_similarity" : 0.6312056737588653, + "maximum_similarity" : 0.6793893129770993, + "matched_token_number" : 89 + }, + "00000_00001-00135_00001" : { + "minimal_similarity" : 0.4041095890410959, + "maximum_similarity" : 0.6020408163265306, + "matched_token_number" : 59 + }, + "00145_00001-00202_00003" : { + "minimal_similarity" : 0.4326241134751773, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00044_00002-00197_00001" : { + "minimal_similarity" : 0.5378787878787878, + "maximum_similarity" : 0.7171717171717171, + "matched_token_number" : 71 + }, + "00141_00002-00198_00001" : { + "minimal_similarity" : 0.3618421052631579, + "maximum_similarity" : 0.5092592592592593, + "matched_token_number" : 55 + }, + "00111_00001-00140_00001" : { + "minimal_similarity" : 0.5609756097560976, + "maximum_similarity" : 0.7931034482758621, + "matched_token_number" : 69 + }, + "00111_00001-00196_00001" : { + "minimal_similarity" : 0.17034700315457413, + "maximum_similarity" : 0.43902439024390244, + "matched_token_number" : 54 + }, + "00014_00001-00142_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 56 + }, + "00125_00001-00138_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00005_00002-00154_00002" : { + "minimal_similarity" : 0.49375, + "maximum_similarity" : 0.6638655462184874, + "matched_token_number" : 79 + }, + "00183_00004-00195_00001" : { + "minimal_similarity" : 0.3404255319148936, + "maximum_similarity" : 0.4067796610169492, + "matched_token_number" : 48 + }, + "00111_00001-00201_00001" : { + "minimal_similarity" : 0.3008130081300813, + "maximum_similarity" : 0.42528735632183906, + "matched_token_number" : 37 + }, + "00183_00004-00200_00002" : { + "minimal_similarity" : 0.48226950354609927, + "maximum_similarity" : 0.5271317829457365, + "matched_token_number" : 68 + }, + "00183_00004-00195_00002" : { + "minimal_similarity" : 0.3404255319148936, + "maximum_similarity" : 0.4067796610169492, + "matched_token_number" : 48 + }, + "00131_00005-00187_00001" : { + "minimal_similarity" : 0.49375, + "maximum_similarity" : 0.5984848484848485, + "matched_token_number" : 79 + }, + "00014_00001-00135_00001" : { + "minimal_similarity" : 0.4589041095890411, + "maximum_similarity" : 0.6203703703703703, + "matched_token_number" : 67 + }, + "00140_00001-00155_00001" : { + "minimal_similarity" : 0.5747126436781609, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00113_00002-00142_00001" : { + "minimal_similarity" : 0.5737704918032787, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00127_00002-00138_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00113_00002-00145_00001" : { + "minimal_similarity" : 0.943089430894309, + "maximum_similarity" : 0.9508196721311475, + "matched_token_number" : 116 + }, + "00000_00003-00097_00002" : { + "minimal_similarity" : 0.40336134453781514, + "maximum_similarity" : 0.4528301886792453, + "matched_token_number" : 48 + }, + "00129_00008-00192_00002" : { + "minimal_similarity" : 0.3829787234042553, + "maximum_similarity" : 0.6870229007633588, + "matched_token_number" : 90 + }, + "00141_00002-00160_00001" : { + "minimal_similarity" : 0.6029411764705882, + "maximum_similarity" : 0.7592592592592593, + "matched_token_number" : 82 + }, + "00129_00008-00192_00001" : { + "minimal_similarity" : 0.425531914893617, + "maximum_similarity" : 0.6451612903225806, + "matched_token_number" : 100 + }, + "00145_00001-00194_00001" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00000_00005-00135_00001" : { + "minimal_similarity" : 0.4246575342465753, + "maximum_similarity" : 0.5166666666666667, + "matched_token_number" : 62 + }, + "00153_00001-00156_00002" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00031_00003-00195_00001" : { + "minimal_similarity" : 0.3728813559322034, + "maximum_similarity" : 0.5176470588235295, + "matched_token_number" : 44 + }, + "00031_00003-00195_00002" : { + "minimal_similarity" : 0.3728813559322034, + "maximum_similarity" : 0.5176470588235295, + "matched_token_number" : 44 + }, + "00113_00002-00201_00001" : { + "minimal_similarity" : 0.30327868852459017, + "maximum_similarity" : 0.42528735632183906, + "matched_token_number" : 37 + }, + "00153_00001-00156_00003" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00113_00002-00196_00001" : { + "minimal_similarity" : 0.17034700315457413, + "maximum_similarity" : 0.4426229508196721, + "matched_token_number" : 54 + }, + "00097_00002-00145_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5754716981132075, + "matched_token_number" : 61 + }, + "00013_00002-00120_00001" : { + "minimal_similarity" : 0.4067796610169492, + "maximum_similarity" : 0.5052631578947369, + "matched_token_number" : 48 + }, + "00000_00005-00186_00004" : { + "minimal_similarity" : 0.39166666666666666, + "maximum_similarity" : 0.44339622641509435, + "matched_token_number" : 47 + }, + "00111_00001-00138_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00127_00002-00196_00001" : { + "minimal_similarity" : 0.17034700315457413, + "maximum_similarity" : 0.43902439024390244, + "matched_token_number" : 54 + }, + "00000_00005-00186_00002" : { + "minimal_similarity" : 0.4492753623188406, + "maximum_similarity" : 0.5166666666666667, + "matched_token_number" : 62 + }, + "00000_00001-00186_00002" : { + "minimal_similarity" : 0.39855072463768115, + "maximum_similarity" : 0.5612244897959183, + "matched_token_number" : 55 + }, + "00125_00001-00145_00001" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00000_00001-00186_00004" : { + "minimal_similarity" : 0.4811320754716981, + "maximum_similarity" : 0.5204081632653061, + "matched_token_number" : 51 + }, + "00147_00001-00156_00003" : { + "minimal_similarity" : 0.35294117647058826, + "maximum_similarity" : 0.4067796610169492, + "matched_token_number" : 48 + }, + "00147_00001-00156_00002" : { + "minimal_similarity" : 0.35294117647058826, + "maximum_similarity" : 0.4067796610169492, + "matched_token_number" : 48 + }, + "00119_00001-00147_00001" : { + "minimal_similarity" : 0.4152542372881356, + "maximum_similarity" : 0.4537037037037037, + "matched_token_number" : 49 + }, + "00000_00003-00156_00002" : { + "minimal_similarity" : 0.34558823529411764, + "maximum_similarity" : 0.3949579831932773, + "matched_token_number" : 47 + }, + "00131_00005-00194_00001" : { + "minimal_similarity" : 0.3375, + "maximum_similarity" : 0.5, + "matched_token_number" : 54 + }, + "00000_00003-00156_00003" : { + "minimal_similarity" : 0.34558823529411764, + "maximum_similarity" : 0.3949579831932773, + "matched_token_number" : 47 + }, + "00198_00001-00201_00001" : { + "minimal_similarity" : 0.2631578947368421, + "maximum_similarity" : 0.45977011494252873, + "matched_token_number" : 40 + }, + "00186_00002-00193_00001" : { + "minimal_similarity" : 0.5579710144927537, + "maximum_similarity" : 0.5789473684210527, + "matched_token_number" : 77 + }, + "00133_00001-00160_00001" : { + "minimal_similarity" : 0.6102941176470589, + "maximum_similarity" : 0.6747967479674797, + "matched_token_number" : 83 + }, + "00153_00001-00160_00001" : { + "minimal_similarity" : 0.6102941176470589, + "maximum_similarity" : 0.6747967479674797, + "matched_token_number" : 83 + }, + "00125_00001-00196_00001" : { + "minimal_similarity" : 0.17034700315457413, + "maximum_similarity" : 0.43902439024390244, + "matched_token_number" : 54 + }, + "00044_00002-00153_00001" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.5656565656565656, + "matched_token_number" : 56 + }, + "00014_00001-00193_00001" : { + "minimal_similarity" : 0.518796992481203, + "maximum_similarity" : 0.6388888888888888, + "matched_token_number" : 69 + }, + "00111_00001-00142_00001" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00192_00001-00197_00001" : { + "minimal_similarity" : 0.7612903225806451, + "maximum_similarity" : 0.8939393939393939, + "matched_token_number" : 118 + }, + "00077_00001-00111_00001" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00097_00002-00204_00001" : { + "minimal_similarity" : 0.44166666666666665, + "maximum_similarity" : 0.5, + "matched_token_number" : 53 + }, + "00127_00002-00145_00001" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00153_00001-00184_00002" : { + "minimal_similarity" : 0.5203252032520326, + "maximum_similarity" : 0.6808510638297872, + "matched_token_number" : 64 + }, + "00153_00001-00184_00003" : { + "minimal_similarity" : 0.5203252032520326, + "maximum_similarity" : 0.6808510638297872, + "matched_token_number" : 64 + }, + "00134_00001-00200_00002" : { + "minimal_similarity" : 0.3643410852713178, + "maximum_similarity" : 0.5802469135802469, + "matched_token_number" : 47 + }, + "00184_00003-00201_00001" : { + "minimal_similarity" : 0.3617021276595745, + "maximum_similarity" : 0.39080459770114945, + "matched_token_number" : 34 + }, + "00113_00002-00121_00001" : { + "minimal_similarity" : 0.6911764705882353, + "maximum_similarity" : 0.7704918032786885, + "matched_token_number" : 94 + }, + "00131_00005-00196_00001" : { + "minimal_similarity" : 0.1640378548895899, + "maximum_similarity" : 0.325, + "matched_token_number" : 52 + }, + "00119_00001-00145_00001" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00121_00001-00138_00001" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00031_00003-00193_00001" : { + "minimal_similarity" : 0.40601503759398494, + "maximum_similarity" : 0.6352941176470588, + "matched_token_number" : 54 + }, + "00126_00002-00197_00001" : { + "minimal_similarity" : 0.4393939393939394, + "maximum_similarity" : 0.4915254237288136, + "matched_token_number" : 58 + }, + "00005_00002-00014_00001" : { + "minimal_similarity" : 0.3375, + "maximum_similarity" : 0.5, + "matched_token_number" : 54 + }, + "00000_00005-00121_00001" : { + "minimal_similarity" : 0.3382352941176471, + "maximum_similarity" : 0.38333333333333336, + "matched_token_number" : 46 + }, + "00160_00001-00183_00004" : { + "minimal_similarity" : 0.574468085106383, + "maximum_similarity" : 0.5955882352941176, + "matched_token_number" : 81 + }, + "00127_00002-00131_00005" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00031_00002-00113_00002" : { + "minimal_similarity" : 0.4672131147540984, + "maximum_similarity" : 0.6195652173913043, + "matched_token_number" : 57 + }, + "00000_00005-00126_00002" : { + "minimal_similarity" : 0.49166666666666664, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00127_00002-00184_00003" : { + "minimal_similarity" : 0.5203252032520326, + "maximum_similarity" : 0.6808510638297872, + "matched_token_number" : 64 + }, + "00000_00003-00121_00001" : { + "minimal_similarity" : 0.36764705882352944, + "maximum_similarity" : 0.42016806722689076, + "matched_token_number" : 50 + }, + "00127_00002-00184_00002" : { + "minimal_similarity" : 0.5203252032520326, + "maximum_similarity" : 0.6808510638297872, + "matched_token_number" : 64 + }, + "00133_00001-00200_00002" : { + "minimal_similarity" : 0.5658914728682171, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00031_00003-00153_00001" : { + "minimal_similarity" : 0.43902439024390244, + "maximum_similarity" : 0.6352941176470588, + "matched_token_number" : 54 + }, + "00199_00001-00203_00002" : { + "minimal_similarity" : 0.46715328467153283, + "maximum_similarity" : 0.6736842105263158, + "matched_token_number" : 64 + }, + "00000_00002-00187_00001" : { + "minimal_similarity" : 0.3787878787878788, + "maximum_similarity" : 0.43478260869565216, + "matched_token_number" : 50 + }, + "00013_00002-00197_00001" : { + "minimal_similarity" : 0.4621212121212121, + "maximum_similarity" : 0.6421052631578947, + "matched_token_number" : 61 + }, + "00111_00001-00187_00001" : { + "minimal_similarity" : 0.5909090909090909, + "maximum_similarity" : 0.6341463414634146, + "matched_token_number" : 78 + }, + "00005_00002-00140_00001" : { + "minimal_similarity" : 0.3375, + "maximum_similarity" : 0.6206896551724138, + "matched_token_number" : 54 + }, + "00177_00003-00198_00001" : { + "minimal_similarity" : 0.4342105263157895, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00126_00002-00131_00005" : { + "minimal_similarity" : 0.46875, + "maximum_similarity" : 0.635593220338983, + "matched_token_number" : 75 + }, + "00005_00002-00198_00001" : { + "minimal_similarity" : 0.49375, + "maximum_similarity" : 0.5197368421052632, + "matched_token_number" : 79 + }, + "00000_00001-00147_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5714285714285714, + "matched_token_number" : 56 + }, + "00111_00001-00147_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00000_00003-00147_00001" : { + "minimal_similarity" : 0.40336134453781514, + "maximum_similarity" : 0.4067796610169492, + "matched_token_number" : 48 + }, + "00119_00001-00193_00001" : { + "minimal_similarity" : 0.518796992481203, + "maximum_similarity" : 0.6388888888888888, + "matched_token_number" : 69 + }, + "00145_00001-00204_00001" : { + "minimal_similarity" : 0.5447154471544715, + "maximum_similarity" : 0.5583333333333333, + "matched_token_number" : 67 + }, + "00000_00003-00193_00001" : { + "minimal_similarity" : 0.45864661654135336, + "maximum_similarity" : 0.5126050420168067, + "matched_token_number" : 61 + }, + "00156_00003-00184_00003" : { + "minimal_similarity" : 0.38235294117647056, + "maximum_similarity" : 0.5531914893617021, + "matched_token_number" : 52 + }, + "00183_00004-00197_00001" : { + "minimal_similarity" : 0.5886524822695035, + "maximum_similarity" : 0.6287878787878788, + "matched_token_number" : 83 + }, + "00156_00003-00184_00002" : { + "minimal_similarity" : 0.38235294117647056, + "maximum_similarity" : 0.5531914893617021, + "matched_token_number" : 52 + }, + "00147_00001-00153_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00000_00005-00153_00001" : { + "minimal_similarity" : 0.4634146341463415, + "maximum_similarity" : 0.475, + "matched_token_number" : 57 + }, + "00154_00002-00201_00001" : { + "minimal_similarity" : 0.2857142857142857, + "maximum_similarity" : 0.39080459770114945, + "matched_token_number" : 34 + }, + "00142_00001-00193_00001" : { + "minimal_similarity" : 0.42857142857142855, + "maximum_similarity" : 0.4830508474576271, + "matched_token_number" : 57 + }, + "00156_00002-00197_00001" : { + "minimal_similarity" : 0.5367647058823529, + "maximum_similarity" : 0.553030303030303, + "matched_token_number" : 73 + }, + "00044_00002-00155_00001" : { + "minimal_similarity" : 0.4444444444444444, + "maximum_similarity" : 0.5057471264367817, + "matched_token_number" : 44 + }, + "00077_00001-00155_00001" : { + "minimal_similarity" : 0.3125, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00121_00001-00133_00001" : { + "minimal_similarity" : 0.6985294117647058, + "maximum_similarity" : 0.7723577235772358, + "matched_token_number" : 95 + }, + "00044_00002-00195_00002" : { + "minimal_similarity" : 0.3813559322033898, + "maximum_similarity" : 0.45454545454545453, + "matched_token_number" : 45 + }, + "00044_00002-00195_00001" : { + "minimal_similarity" : 0.3813559322033898, + "maximum_similarity" : 0.45454545454545453, + "matched_token_number" : 45 + }, + "00005_00002-00177_00003" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00000_00001-00193_00001" : { + "minimal_similarity" : 0.42105263157894735, + "maximum_similarity" : 0.5714285714285714, + "matched_token_number" : 56 + }, + "00119_00001-00177_00003" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00130_00002-00177_00003" : { + "minimal_similarity" : 0.5609756097560976, + "maximum_similarity" : 0.7931034482758621, + "matched_token_number" : 69 + }, + "00000_00003-00126_00002" : { + "minimal_similarity" : 0.4957983193277311, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00184_00003-00195_00001" : { + "minimal_similarity" : 0.4661016949152542, + "maximum_similarity" : 0.5851063829787234, + "matched_token_number" : 55 + }, + "00127_00002-00136_00002" : { + "minimal_similarity" : 0.4, + "maximum_similarity" : 0.5853658536585366, + "matched_token_number" : 72 + }, + "00195_00002-00199_00001" : { + "minimal_similarity" : 0.4830508474576271, + "maximum_similarity" : 0.6, + "matched_token_number" : 57 + }, + "00137_00002-00154_00002" : { + "minimal_similarity" : 0.8780487804878049, + "maximum_similarity" : 0.907563025210084, + "matched_token_number" : 108 + }, + "00184_00003-00195_00002" : { + "minimal_similarity" : 0.4661016949152542, + "maximum_similarity" : 0.5851063829787234, + "matched_token_number" : 55 + }, + "00113_00002-00140_00001" : { + "minimal_similarity" : 0.5655737704918032, + "maximum_similarity" : 0.7931034482758621, + "matched_token_number" : 69 + }, + "00111_00001-00204_00001" : { + "minimal_similarity" : 0.5447154471544715, + "maximum_similarity" : 0.5583333333333333, + "matched_token_number" : 67 + }, + "00000_00003-00142_00001" : { + "minimal_similarity" : 0.4957983193277311, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00000_00001-00142_00001" : { + "minimal_similarity" : 0.4406779661016949, + "maximum_similarity" : 0.5306122448979592, + "matched_token_number" : 52 + }, + "00177_00003-00193_00001" : { + "minimal_similarity" : 0.5488721804511278, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00119_00001-00126_00002" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 56 + }, + "00013_00002-00192_00001" : { + "minimal_similarity" : 0.36774193548387096, + "maximum_similarity" : 0.6, + "matched_token_number" : 57 + }, + "00031_00002-00134_00001" : { + "minimal_similarity" : 0.42391304347826086, + "maximum_similarity" : 0.48148148148148145, + "matched_token_number" : 39 + }, + "00013_00002-00192_00002" : { + "minimal_similarity" : 0.42748091603053434, + "maximum_similarity" : 0.5894736842105263, + "matched_token_number" : 56 + }, + "00005_00002-00193_00001" : { + "minimal_similarity" : 0.44375, + "maximum_similarity" : 0.5338345864661654, + "matched_token_number" : 71 + }, + "00000_00002-00155_00001" : { + "minimal_similarity" : 0.4, + "maximum_similarity" : 0.5287356321839081, + "matched_token_number" : 46 + }, + "00031_00003-00177_00003" : { + "minimal_similarity" : 0.43902439024390244, + "maximum_similarity" : 0.6352941176470588, + "matched_token_number" : 54 + }, + "00145_00001-00187_00001" : { + "minimal_similarity" : 0.5909090909090909, + "maximum_similarity" : 0.6341463414634146, + "matched_token_number" : 78 + }, + "00013_00002-00125_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.6421052631578947, + "matched_token_number" : 61 + }, + "00000_00003-00198_00001" : { + "minimal_similarity" : 0.4342105263157895, + "maximum_similarity" : 0.5546218487394958, + "matched_token_number" : 66 + }, + "00005_00002-00121_00001" : { + "minimal_similarity" : 0.475, + "maximum_similarity" : 0.5588235294117647, + "matched_token_number" : 76 + }, + "00177_00003-00196_00001" : { + "minimal_similarity" : 0.17034700315457413, + "maximum_similarity" : 0.43902439024390244, + "matched_token_number" : 54 + }, + "00133_00001-00141_00002" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00000_00001-00195_00002" : { + "minimal_similarity" : 0.4406779661016949, + "maximum_similarity" : 0.5306122448979592, + "matched_token_number" : 52 + }, + "00031_00002-00187_00001" : { + "minimal_similarity" : 0.4090909090909091, + "maximum_similarity" : 0.5869565217391305, + "matched_token_number" : 54 + }, + "00000_00001-00195_00001" : { + "minimal_similarity" : 0.4406779661016949, + "maximum_similarity" : 0.5306122448979592, + "matched_token_number" : 52 + }, + "00121_00001-00131_00005" : { + "minimal_similarity" : 0.475, + "maximum_similarity" : 0.5588235294117647, + "matched_token_number" : 76 + }, + "00000_00001-00198_00001" : { + "minimal_similarity" : 0.4276315789473684, + "maximum_similarity" : 0.6632653061224489, + "matched_token_number" : 65 + }, + "00177_00003-00204_00001" : { + "minimal_similarity" : 0.5447154471544715, + "maximum_similarity" : 0.5583333333333333, + "matched_token_number" : 67 + }, + "00125_00001-00178_00002" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00005_00002-00204_00001" : { + "minimal_similarity" : 0.5125, + "maximum_similarity" : 0.6833333333333333, + "matched_token_number" : 82 + }, + "00077_00001-00153_00001" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00140_00001-00195_00002" : { + "minimal_similarity" : 0.4406779661016949, + "maximum_similarity" : 0.5977011494252874, + "matched_token_number" : 52 + }, + "00140_00001-00195_00001" : { + "minimal_similarity" : 0.4406779661016949, + "maximum_similarity" : 0.5977011494252874, + "matched_token_number" : 52 + }, + "00121_00001-00184_00003" : { + "minimal_similarity" : 0.3897058823529412, + "maximum_similarity" : 0.5638297872340425, + "matched_token_number" : 53 + }, + "00121_00001-00184_00002" : { + "minimal_similarity" : 0.3897058823529412, + "maximum_similarity" : 0.5638297872340425, + "matched_token_number" : 53 + }, + "00119_00001-00156_00003" : { + "minimal_similarity" : 0.5220588235294118, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00092_00001-00156_00002" : { + "minimal_similarity" : 0.35294117647058826, + "maximum_similarity" : 0.4067796610169492, + "matched_token_number" : 48 + }, + "00092_00001-00156_00003" : { + "minimal_similarity" : 0.35294117647058826, + "maximum_similarity" : 0.4067796610169492, + "matched_token_number" : 48 + }, + "00136_00002-00183_00004" : { + "minimal_similarity" : 0.45, + "maximum_similarity" : 0.574468085106383, + "matched_token_number" : 81 + }, + "00000_00003-00195_00002" : { + "minimal_similarity" : 0.4957983193277311, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00119_00001-00156_00002" : { + "minimal_similarity" : 0.5220588235294118, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00000_00003-00195_00001" : { + "minimal_similarity" : 0.4957983193277311, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00000_00002-00077_00001" : { + "minimal_similarity" : 0.39375, + "maximum_similarity" : 0.5478260869565217, + "matched_token_number" : 63 + }, + "00138_00001-00199_00001" : { + "minimal_similarity" : 0.3898305084745763, + "maximum_similarity" : 0.4842105263157895, + "matched_token_number" : 46 + }, + "00005_00002-00196_00001" : { + "minimal_similarity" : 0.1640378548895899, + "maximum_similarity" : 0.325, + "matched_token_number" : 52 + }, + "00013_00002-00160_00001" : { + "minimal_similarity" : 0.39705882352941174, + "maximum_similarity" : 0.5684210526315789, + "matched_token_number" : 54 + }, + "00044_00002-00192_00001" : { + "minimal_similarity" : 0.45806451612903226, + "maximum_similarity" : 0.7171717171717171, + "matched_token_number" : 71 + }, + "00044_00002-00192_00002" : { + "minimal_similarity" : 0.5190839694656488, + "maximum_similarity" : 0.6868686868686869, + "matched_token_number" : 68 + }, + "00126_00002-00199_00001" : { + "minimal_similarity" : 0.4830508474576271, + "maximum_similarity" : 0.6, + "matched_token_number" : 57 + }, + "00127_00002-00133_00001" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00195_00002-00196_00001" : { + "minimal_similarity" : 0.17981072555205047, + "maximum_similarity" : 0.4830508474576271, + "matched_token_number" : 57 + }, + "00156_00003-00187_00001" : { + "minimal_similarity" : 0.5367647058823529, + "maximum_similarity" : 0.553030303030303, + "matched_token_number" : 73 + }, + "00014_00001-00095_00003" : { + "minimal_similarity" : 0.313953488372093, + "maximum_similarity" : 0.5, + "matched_token_number" : 54 + }, + "00111_00001-00131_00005" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00134_00001-00199_00001" : { + "minimal_similarity" : 0.45263157894736844, + "maximum_similarity" : 0.5308641975308642, + "matched_token_number" : 43 + }, + "00138_00001-00183_00004" : { + "minimal_similarity" : 0.3829787234042553, + "maximum_similarity" : 0.4576271186440678, + "matched_token_number" : 54 + }, + "00092_00001-00135_00001" : { + "minimal_similarity" : 0.4452054794520548, + "maximum_similarity" : 0.5508474576271186, + "matched_token_number" : 65 + }, + "00000_00002-00134_00001" : { + "minimal_similarity" : 0.3652173913043478, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 42 + }, + "00119_00001-00129_00008" : { + "minimal_similarity" : 0.2978723404255319, + "maximum_similarity" : 0.6481481481481481, + "matched_token_number" : 70 + }, + "00121_00001-00154_00002" : { + "minimal_similarity" : 0.6397058823529411, + "maximum_similarity" : 0.7310924369747899, + "matched_token_number" : 87 + }, + "00184_00002-00187_00001" : { + "minimal_similarity" : 0.5227272727272727, + "maximum_similarity" : 0.7340425531914894, + "matched_token_number" : 69 + }, + "00202_00002-00203_00002" : { + "minimal_similarity" : 0.6737588652482269, + "maximum_similarity" : 0.6934306569343066, + "matched_token_number" : 95 + }, + "00005_00002-00145_00001" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00119_00001-00140_00001" : { + "minimal_similarity" : 0.46296296296296297, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00031_00003-00126_00002" : { + "minimal_similarity" : 0.3728813559322034, + "maximum_similarity" : 0.5176470588235295, + "matched_token_number" : 44 + }, + "00113_00002-00126_00002" : { + "minimal_similarity" : 0.5737704918032787, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00092_00001-00154_00002" : { + "minimal_similarity" : 0.4957983193277311, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00077_00001-00137_00002" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00200_00002-00202_00002" : { + "minimal_similarity" : 0.48936170212765956, + "maximum_similarity" : 0.5348837209302325, + "matched_token_number" : 69 + }, + "00130_00002-00204_00001" : { + "minimal_similarity" : 0.4583333333333333, + "maximum_similarity" : 0.632183908045977, + "matched_token_number" : 55 + }, + "00134_00001-00178_00002" : { + "minimal_similarity" : 0.4715447154471545, + "maximum_similarity" : 0.7160493827160493, + "matched_token_number" : 58 + }, + "00044_00002-00120_00001" : { + "minimal_similarity" : 0.3813559322033898, + "maximum_similarity" : 0.45454545454545453, + "matched_token_number" : 45 + }, + "00141_00002-00184_00003" : { + "minimal_similarity" : 0.5092592592592593, + "maximum_similarity" : 0.5851063829787234, + "matched_token_number" : 55 + }, + "00097_00002-00133_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5754716981132075, + "matched_token_number" : 61 + }, + "00141_00002-00184_00002" : { + "minimal_similarity" : 0.5092592592592593, + "maximum_similarity" : 0.5851063829787234, + "matched_token_number" : 55 + }, + "00140_00001-00202_00003" : { + "minimal_similarity" : 0.40425531914893614, + "maximum_similarity" : 0.6551724137931034, + "matched_token_number" : 57 + }, + "00013_00002-00141_00002" : { + "minimal_similarity" : 0.5185185185185185, + "maximum_similarity" : 0.5894736842105263, + "matched_token_number" : 56 + }, + "00000_00003-00013_00002" : { + "minimal_similarity" : 0.37815126050420167, + "maximum_similarity" : 0.47368421052631576, + "matched_token_number" : 45 + }, + "00135_00001-00145_00001" : { + "minimal_similarity" : 0.5273972602739726, + "maximum_similarity" : 0.6260162601626016, + "matched_token_number" : 77 + }, + "00097_00002-00113_00002" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.5754716981132075, + "matched_token_number" : 61 + }, + "00092_00001-00187_00001" : { + "minimal_similarity" : 0.48484848484848486, + "maximum_similarity" : 0.5423728813559322, + "matched_token_number" : 64 + }, + "00140_00001-00202_00002" : { + "minimal_similarity" : 0.40425531914893614, + "maximum_similarity" : 0.6551724137931034, + "matched_token_number" : 57 + }, + "00113_00002-00177_00003" : { + "minimal_similarity" : 0.943089430894309, + "maximum_similarity" : 0.9508196721311475, + "matched_token_number" : 116 + }, + "00129_00008-00153_00001" : { + "minimal_similarity" : 0.3191489361702128, + "maximum_similarity" : 0.6097560975609756, + "matched_token_number" : 75 + }, + "00000_00002-00136_00002" : { + "minimal_similarity" : 0.3055555555555556, + "maximum_similarity" : 0.4782608695652174, + "matched_token_number" : 55 + }, + "00136_00002-00137_00002" : { + "minimal_similarity" : 0.4, + "maximum_similarity" : 0.5853658536585366, + "matched_token_number" : 72 + }, + "00142_00001-00196_00001" : { + "minimal_similarity" : 0.17981072555205047, + "maximum_similarity" : 0.4830508474576271, + "matched_token_number" : 57 + }, + "00130_00002-00140_00001" : { + "minimal_similarity" : 0.9540229885057471, + "maximum_similarity" : 0.9540229885057471, + "matched_token_number" : 83 + }, + "00195_00002-00201_00001" : { + "minimal_similarity" : 0.3389830508474576, + "maximum_similarity" : 0.45977011494252873, + "matched_token_number" : 40 + }, + "00130_00002-00160_00001" : { + "minimal_similarity" : 0.4117647058823529, + "maximum_similarity" : 0.6436781609195402, + "matched_token_number" : 56 + }, + "00031_00003-00156_00002" : { + "minimal_similarity" : 0.3382352941176471, + "maximum_similarity" : 0.5411764705882353, + "matched_token_number" : 46 + }, + "00031_00003-00156_00003" : { + "minimal_similarity" : 0.3382352941176471, + "maximum_similarity" : 0.5411764705882353, + "matched_token_number" : 46 + }, + "00160_00001-00186_00004" : { + "minimal_similarity" : 0.47794117647058826, + "maximum_similarity" : 0.6132075471698113, + "matched_token_number" : 65 + }, + "00184_00003-00193_00001" : { + "minimal_similarity" : 0.42857142857142855, + "maximum_similarity" : 0.6063829787234043, + "matched_token_number" : 57 + }, + "00031_00002-00136_00002" : { + "minimal_similarity" : 0.4, + "maximum_similarity" : 0.782608695652174, + "matched_token_number" : 72 + }, + "00160_00001-00186_00002" : { + "minimal_similarity" : 0.4782608695652174, + "maximum_similarity" : 0.4852941176470588, + "matched_token_number" : 66 + }, + "00133_00001-00193_00001" : { + "minimal_similarity" : 0.5488721804511278, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00120_00001-00183_00004" : { + "minimal_similarity" : 0.3404255319148936, + "maximum_similarity" : 0.4067796610169492, + "matched_token_number" : 48 + }, + "00184_00003-00203_00002" : { + "minimal_similarity" : 0.45255474452554745, + "maximum_similarity" : 0.6595744680851063, + "matched_token_number" : 62 + }, + "00155_00001-00187_00001" : { + "minimal_similarity" : 0.42424242424242425, + "maximum_similarity" : 0.6436781609195402, + "matched_token_number" : 56 + }, + "00031_00002-00077_00001" : { + "minimal_similarity" : 0.35, + "maximum_similarity" : 0.6086956521739131, + "matched_token_number" : 56 + }, + "00095_00003-00187_00001" : { + "minimal_similarity" : 0.37209302325581395, + "maximum_similarity" : 0.48484848484848486, + "matched_token_number" : 64 + }, + "00140_00001-00192_00001" : { + "minimal_similarity" : 0.36774193548387096, + "maximum_similarity" : 0.6551724137931034, + "matched_token_number" : 57 + }, + "00140_00001-00192_00002" : { + "minimal_similarity" : 0.4198473282442748, + "maximum_similarity" : 0.632183908045977, + "matched_token_number" : 55 + }, + "00092_00001-00097_00002" : { + "minimal_similarity" : 0.423728813559322, + "maximum_similarity" : 0.4716981132075472, + "matched_token_number" : 50 + }, + "00156_00002-00203_00002" : { + "minimal_similarity" : 0.5109489051094891, + "maximum_similarity" : 0.5147058823529411, + "matched_token_number" : 70 + }, + "00095_00003-00154_00002" : { + "minimal_similarity" : 0.36046511627906974, + "maximum_similarity" : 0.5210084033613446, + "matched_token_number" : 62 + }, + "00147_00001-00183_00004" : { + "minimal_similarity" : 0.3829787234042553, + "maximum_similarity" : 0.4576271186440678, + "matched_token_number" : 54 + }, + "00120_00001-00136_00002" : { + "minimal_similarity" : 0.2722222222222222, + "maximum_similarity" : 0.4152542372881356, + "matched_token_number" : 49 + }, + "00133_00001-00192_00002" : { + "minimal_similarity" : 0.5267175572519084, + "maximum_similarity" : 0.5609756097560976, + "matched_token_number" : 69 + }, + "00133_00001-00192_00001" : { + "minimal_similarity" : 0.44516129032258067, + "maximum_similarity" : 0.5609756097560976, + "matched_token_number" : 69 + }, + "00130_00002-00147_00001" : { + "minimal_similarity" : 0.423728813559322, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00000_00003-00201_00001" : { + "minimal_similarity" : 0.2773109243697479, + "maximum_similarity" : 0.3793103448275862, + "matched_token_number" : 33 + }, + "00135_00001-00140_00001" : { + "minimal_similarity" : 0.4041095890410959, + "maximum_similarity" : 0.6781609195402298, + "matched_token_number" : 59 + }, + "00013_00002-00031_00003" : { + "minimal_similarity" : 0.6105263157894737, + "maximum_similarity" : 0.6823529411764706, + "matched_token_number" : 58 + }, + "00130_00002-00193_00001" : { + "minimal_similarity" : 0.41353383458646614, + "maximum_similarity" : 0.632183908045977, + "matched_token_number" : 55 + }, + "00013_00002-00031_00002" : { + "minimal_similarity" : 0.5894736842105263, + "maximum_similarity" : 0.6086956521739131, + "matched_token_number" : 56 + }, + "00005_00002-00142_00001" : { + "minimal_similarity" : 0.46875, + "maximum_similarity" : 0.635593220338983, + "matched_token_number" : 75 + }, + "00142_00001-00201_00001" : { + "minimal_similarity" : 0.3389830508474576, + "maximum_similarity" : 0.45977011494252873, + "matched_token_number" : 40 + }, + "00134_00001-00202_00002" : { + "minimal_similarity" : 0.3262411347517731, + "maximum_similarity" : 0.5679012345679012, + "matched_token_number" : 46 + }, + "00134_00001-00202_00003" : { + "minimal_similarity" : 0.3333333333333333, + "maximum_similarity" : 0.5802469135802469, + "matched_token_number" : 47 + }, + "00153_00001-00186_00002" : { + "minimal_similarity" : 0.4782608695652174, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00000_00003-00177_00003" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.47058823529411764, + "matched_token_number" : 56 + }, + "00153_00001-00186_00004" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.5283018867924528, + "matched_token_number" : 56 + }, + "00135_00001-00199_00001" : { + "minimal_similarity" : 0.4452054794520548, + "maximum_similarity" : 0.6842105263157895, + "matched_token_number" : 65 + }, + "00014_00001-00121_00001" : { + "minimal_similarity" : 0.49264705882352944, + "maximum_similarity" : 0.6203703703703703, + "matched_token_number" : 67 + }, + "00154_00002-00178_00002" : { + "minimal_similarity" : 0.8780487804878049, + "maximum_similarity" : 0.907563025210084, + "matched_token_number" : 108 + }, + "00135_00001-00204_00001" : { + "minimal_similarity" : 0.4863013698630137, + "maximum_similarity" : 0.5916666666666667, + "matched_token_number" : 71 + }, + "00013_00002-00200_00002" : { + "minimal_similarity" : 0.3953488372093023, + "maximum_similarity" : 0.5368421052631579, + "matched_token_number" : 51 + }, + "00000_00003-00200_00002" : { + "minimal_similarity" : 0.4728682170542636, + "maximum_similarity" : 0.5126050420168067, + "matched_token_number" : 61 + }, + "00013_00002-00195_00002" : { + "minimal_similarity" : 0.4067796610169492, + "maximum_similarity" : 0.5052631578947369, + "matched_token_number" : 48 + }, + "00013_00002-00195_00001" : { + "minimal_similarity" : 0.4067796610169492, + "maximum_similarity" : 0.5052631578947369, + "matched_token_number" : 48 + }, + "00120_00001-00131_00005" : { + "minimal_similarity" : 0.46875, + "maximum_similarity" : 0.635593220338983, + "matched_token_number" : 75 + }, + "00142_00001-00145_00001" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00120_00001-00134_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.691358024691358, + "matched_token_number" : 56 + }, + "00077_00001-00183_00004" : { + "minimal_similarity" : 0.44375, + "maximum_similarity" : 0.5035460992907801, + "matched_token_number" : 71 + }, + "00120_00001-00187_00001" : { + "minimal_similarity" : 0.4393939393939394, + "maximum_similarity" : 0.4915254237288136, + "matched_token_number" : 58 + }, + "00142_00001-00198_00001" : { + "minimal_similarity" : 0.3881578947368421, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00130_00002-00142_00001" : { + "minimal_similarity" : 0.4406779661016949, + "maximum_similarity" : 0.5977011494252874, + "matched_token_number" : 52 + }, + "00133_00001-00177_00003" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00134_00001-00141_00002" : { + "minimal_similarity" : 0.4722222222222222, + "maximum_similarity" : 0.6296296296296297, + "matched_token_number" : 51 + }, + "00156_00002-00192_00002" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.5190839694656488, + "matched_token_number" : 68 + }, + "00156_00002-00192_00001" : { + "minimal_similarity" : 0.432258064516129, + "maximum_similarity" : 0.49264705882352944, + "matched_token_number" : 67 + }, + "00129_00008-00155_00001" : { + "minimal_similarity" : 0.22127659574468084, + "maximum_similarity" : 0.5977011494252874, + "matched_token_number" : 52 + }, + "00000_00003-00031_00002" : { + "minimal_similarity" : 0.44537815126050423, + "maximum_similarity" : 0.5760869565217391, + "matched_token_number" : 53 + }, + "00000_00003-00031_00003" : { + "minimal_similarity" : 0.4369747899159664, + "maximum_similarity" : 0.611764705882353, + "matched_token_number" : 52 + }, + "00147_00001-00184_00002" : { + "minimal_similarity" : 0.3983050847457627, + "maximum_similarity" : 0.5, + "matched_token_number" : 47 + }, + "00147_00001-00184_00003" : { + "minimal_similarity" : 0.3983050847457627, + "maximum_similarity" : 0.5, + "matched_token_number" : 47 + }, + "00156_00002-00195_00002" : { + "minimal_similarity" : 0.34558823529411764, + "maximum_similarity" : 0.3983050847457627, + "matched_token_number" : 47 + }, + "00134_00001-00194_00001" : { + "minimal_similarity" : 0.4722222222222222, + "maximum_similarity" : 0.6296296296296297, + "matched_token_number" : 51 + }, + "00156_00002-00195_00001" : { + "minimal_similarity" : 0.34558823529411764, + "maximum_similarity" : 0.3983050847457627, + "matched_token_number" : 47 + }, + "00095_00003-00138_00001" : { + "minimal_similarity" : 0.4127906976744186, + "maximum_similarity" : 0.6016949152542372, + "matched_token_number" : 71 + }, + "00013_00002-00203_00002" : { + "minimal_similarity" : 0.46715328467153283, + "maximum_similarity" : 0.6736842105263158, + "matched_token_number" : 64 + }, + "00005_00002-00126_00002" : { + "minimal_similarity" : 0.46875, + "maximum_similarity" : 0.635593220338983, + "matched_token_number" : 75 + }, + "00200_00002-00201_00001" : { + "minimal_similarity" : 0.35658914728682173, + "maximum_similarity" : 0.5287356321839081, + "matched_token_number" : 46 + }, + "00005_00002-00129_00008" : { + "minimal_similarity" : 0.3021276595744681, + "maximum_similarity" : 0.44375, + "matched_token_number" : 71 + }, + "00135_00001-00194_00001" : { + "minimal_similarity" : 0.4589041095890411, + "maximum_similarity" : 0.6203703703703703, + "matched_token_number" : 67 + }, + "00119_00001-00121_00001" : { + "minimal_similarity" : 0.49264705882352944, + "maximum_similarity" : 0.6203703703703703, + "matched_token_number" : 67 + }, + "00137_00002-00138_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00135_00001-00201_00001" : { + "minimal_similarity" : 0.3150684931506849, + "maximum_similarity" : 0.5287356321839081, + "matched_token_number" : 46 + }, + "00092_00001-00095_00003" : { + "minimal_similarity" : 0.4127906976744186, + "maximum_similarity" : 0.6016949152542372, + "matched_token_number" : 71 + }, + "00000_00005-00097_00002" : { + "minimal_similarity" : 0.36666666666666664, + "maximum_similarity" : 0.41509433962264153, + "matched_token_number" : 44 + }, + "00031_00003-00121_00001" : { + "minimal_similarity" : 0.4117647058823529, + "maximum_similarity" : 0.6588235294117647, + "matched_token_number" : 56 + }, + "00130_00002-00198_00001" : { + "minimal_similarity" : 0.3026315789473684, + "maximum_similarity" : 0.5287356321839081, + "matched_token_number" : 46 + }, + "00121_00001-00187_00001" : { + "minimal_similarity" : 0.5514705882352942, + "maximum_similarity" : 0.5681818181818182, + "matched_token_number" : 75 + }, + "00013_00002-00202_00003" : { + "minimal_similarity" : 0.425531914893617, + "maximum_similarity" : 0.631578947368421, + "matched_token_number" : 60 + }, + "00135_00001-00202_00002" : { + "minimal_similarity" : 0.4726027397260274, + "maximum_similarity" : 0.48936170212765956, + "matched_token_number" : 69 + }, + "00142_00001-00147_00001" : { + "minimal_similarity" : 0.5338983050847458, + "maximum_similarity" : 0.5338983050847458, + "matched_token_number" : 63 + }, + "00141_00002-00183_00004" : { + "minimal_similarity" : 0.425531914893617, + "maximum_similarity" : 0.5555555555555556, + "matched_token_number" : 60 + }, + "00147_00001-00186_00002" : { + "minimal_similarity" : 0.3695652173913043, + "maximum_similarity" : 0.4322033898305085, + "matched_token_number" : 51 + }, + "00147_00001-00186_00004" : { + "minimal_similarity" : 0.423728813559322, + "maximum_similarity" : 0.4716981132075472, + "matched_token_number" : 50 + }, + "00000_00005-00156_00002" : { + "minimal_similarity" : 0.34558823529411764, + "maximum_similarity" : 0.39166666666666666, + "matched_token_number" : 47 + }, + "00000_00005-00156_00003" : { + "minimal_similarity" : 0.34558823529411764, + "maximum_similarity" : 0.39166666666666666, + "matched_token_number" : 47 + }, + "00044_00002-00125_00001" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.5656565656565656, + "matched_token_number" : 56 + }, + "00121_00001-00136_00002" : { + "minimal_similarity" : 0.46111111111111114, + "maximum_similarity" : 0.6102941176470589, + "matched_token_number" : 83 + }, + "00000_00001-00111_00001" : { + "minimal_similarity" : 0.43902439024390244, + "maximum_similarity" : 0.5510204081632653, + "matched_token_number" : 54 + }, + "00077_00001-00186_00002" : { + "minimal_similarity" : 0.4125, + "maximum_similarity" : 0.4782608695652174, + "matched_token_number" : 66 + }, + "00134_00001-00192_00001" : { + "minimal_similarity" : 0.36129032258064514, + "maximum_similarity" : 0.691358024691358, + "matched_token_number" : 56 + }, + "00134_00001-00192_00002" : { + "minimal_similarity" : 0.3893129770992366, + "maximum_similarity" : 0.6296296296296297, + "matched_token_number" : 51 + }, + "00156_00002-00200_00002" : { + "minimal_similarity" : 0.4117647058823529, + "maximum_similarity" : 0.43410852713178294, + "matched_token_number" : 56 + }, + "00135_00001-00196_00001" : { + "minimal_similarity" : 0.2586750788643533, + "maximum_similarity" : 0.5616438356164384, + "matched_token_number" : 82 + }, + "00077_00001-00186_00004" : { + "minimal_similarity" : 0.39375, + "maximum_similarity" : 0.5943396226415094, + "matched_token_number" : 63 + }, + "00130_00002-00145_00001" : { + "minimal_similarity" : 0.5609756097560976, + "maximum_similarity" : 0.7931034482758621, + "matched_token_number" : 69 + }, + "00135_00001-00202_00003" : { + "minimal_similarity" : 0.4657534246575342, + "maximum_similarity" : 0.48226950354609927, + "matched_token_number" : 68 + }, + "00031_00002-00131_00005" : { + "minimal_similarity" : 0.35, + "maximum_similarity" : 0.6086956521739131, + "matched_token_number" : 56 + }, + "00130_00002-00203_00002" : { + "minimal_similarity" : 0.38686131386861317, + "maximum_similarity" : 0.6091954022988506, + "matched_token_number" : 53 + }, + "00130_00002-00196_00001" : { + "minimal_similarity" : 0.10725552050473186, + "maximum_similarity" : 0.39080459770114945, + "matched_token_number" : 34 + }, + "00200_00002-00202_00003" : { + "minimal_similarity" : 0.46808510638297873, + "maximum_similarity" : 0.5116279069767442, + "matched_token_number" : 66 + }, + "00013_00002-00202_00002" : { + "minimal_similarity" : 0.4326241134751773, + "maximum_similarity" : 0.6421052631578947, + "matched_token_number" : 61 + }, + "00077_00001-00134_00001" : { + "minimal_similarity" : 0.33125, + "maximum_similarity" : 0.654320987654321, + "matched_token_number" : 53 + }, + "00142_00001-00204_00001" : { + "minimal_similarity" : 0.4666666666666667, + "maximum_similarity" : 0.4745762711864407, + "matched_token_number" : 56 + }, + "00119_00001-00178_00002" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00130_00002-00136_00002" : { + "minimal_similarity" : 0.29444444444444445, + "maximum_similarity" : 0.6091954022988506, + "matched_token_number" : 53 + }, + "00129_00008-00156_00003" : { + "minimal_similarity" : 0.3276595744680851, + "maximum_similarity" : 0.5661764705882353, + "matched_token_number" : 77 + }, + "00005_00002-00178_00002" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00129_00008-00156_00002" : { + "minimal_similarity" : 0.3276595744680851, + "maximum_similarity" : 0.5661764705882353, + "matched_token_number" : 77 + }, + "00113_00002-00194_00001" : { + "minimal_similarity" : 0.5819672131147541, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00119_00001-00203_00002" : { + "minimal_similarity" : 0.48905109489051096, + "maximum_similarity" : 0.6203703703703703, + "matched_token_number" : 67 + }, + "00044_00002-00092_00001" : { + "minimal_similarity" : 0.3813559322033898, + "maximum_similarity" : 0.45454545454545453, + "matched_token_number" : 45 + }, + "00184_00002-00196_00001" : { + "minimal_similarity" : 0.1608832807570978, + "maximum_similarity" : 0.5425531914893617, + "matched_token_number" : 51 + }, + "00138_00001-00187_00001" : { + "minimal_similarity" : 0.48484848484848486, + "maximum_similarity" : 0.5423728813559322, + "matched_token_number" : 64 + }, + "00137_00002-00147_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00125_00001-00177_00003" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00131_00005-00201_00001" : { + "minimal_similarity" : 0.24375, + "maximum_similarity" : 0.4482758620689655, + "matched_token_number" : 39 + }, + "00196_00001-00204_00001" : { + "minimal_similarity" : 0.19873817034700317, + "maximum_similarity" : 0.525, + "matched_token_number" : 63 + }, + "00135_00001-00155_00001" : { + "minimal_similarity" : 0.3972602739726027, + "maximum_similarity" : 0.6666666666666666, + "matched_token_number" : 58 + }, + "00000_00003-00141_00002" : { + "minimal_similarity" : 0.4957983193277311, + "maximum_similarity" : 0.5462962962962963, + "matched_token_number" : 59 + }, + "00031_00003-00120_00001" : { + "minimal_similarity" : 0.3728813559322034, + "maximum_similarity" : 0.5176470588235295, + "matched_token_number" : 44 + }, + "00120_00001-00140_00001" : { + "minimal_similarity" : 0.4406779661016949, + "maximum_similarity" : 0.5977011494252874, + "matched_token_number" : 52 + }, + "00014_00001-00183_00004" : { + "minimal_similarity" : 0.425531914893617, + "maximum_similarity" : 0.5555555555555556, + "matched_token_number" : 60 + }, + "00147_00001-00192_00001" : { + "minimal_similarity" : 0.38064516129032255, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00031_00003-00133_00001" : { + "minimal_similarity" : 0.43902439024390244, + "maximum_similarity" : 0.6352941176470588, + "matched_token_number" : 54 + }, + "00147_00001-00192_00002" : { + "minimal_similarity" : 0.44274809160305345, + "maximum_similarity" : 0.4915254237288136, + "matched_token_number" : 58 + }, + "00154_00002-00177_00003" : { + "minimal_similarity" : 0.8780487804878049, + "maximum_similarity" : 0.907563025210084, + "matched_token_number" : 108 + }, + "00000_00001-00141_00002" : { + "minimal_similarity" : 0.5277777777777778, + "maximum_similarity" : 0.5816326530612245, + "matched_token_number" : 57 + }, + "00031_00002-00133_00001" : { + "minimal_similarity" : 0.4634146341463415, + "maximum_similarity" : 0.6195652173913043, + "matched_token_number" : 57 + }, + "00178_00002-00192_00001" : { + "minimal_similarity" : 0.44516129032258067, + "maximum_similarity" : 0.5609756097560976, + "matched_token_number" : 69 + }, + "00178_00002-00192_00002" : { + "minimal_similarity" : 0.5267175572519084, + "maximum_similarity" : 0.5609756097560976, + "matched_token_number" : 69 + }, + "00013_00002-00177_00003" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.6421052631578947, + "matched_token_number" : 61 + }, + "00005_00002-00160_00001" : { + "minimal_similarity" : 0.4125, + "maximum_similarity" : 0.4852941176470588, + "matched_token_number" : 66 + }, + "00014_00001-00111_00001" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00127_00002-00130_00002" : { + "minimal_similarity" : 0.5609756097560976, + "maximum_similarity" : 0.7931034482758621, + "matched_token_number" : 69 + }, + "00077_00001-00119_00001" : { + "minimal_similarity" : 0.3375, + "maximum_similarity" : 0.5, + "matched_token_number" : 54 + }, + "00000_00003-00120_00001" : { + "minimal_similarity" : 0.4957983193277311, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00013_00002-00130_00002" : { + "minimal_similarity" : 0.47368421052631576, + "maximum_similarity" : 0.5172413793103449, + "matched_token_number" : 45 + }, + "00000_00002-00120_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.48695652173913045, + "matched_token_number" : 56 + }, + "00044_00002-00097_00002" : { + "minimal_similarity" : 0.3584905660377358, + "maximum_similarity" : 0.3838383838383838, + "matched_token_number" : 38 + }, + "00111_00001-00135_00001" : { + "minimal_similarity" : 0.5273972602739726, + "maximum_similarity" : 0.6260162601626016, + "matched_token_number" : 77 + }, + "00000_00005-00120_00001" : { + "minimal_similarity" : 0.49166666666666664, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00130_00002-00131_00005" : { + "minimal_similarity" : 0.3375, + "maximum_similarity" : 0.6206896551724138, + "matched_token_number" : 54 + }, + "00145_00001-00192_00002" : { + "minimal_similarity" : 0.5267175572519084, + "maximum_similarity" : 0.5609756097560976, + "matched_token_number" : 69 + }, + "00135_00001-00147_00001" : { + "minimal_similarity" : 0.4452054794520548, + "maximum_similarity" : 0.5508474576271186, + "matched_token_number" : 65 + }, + "00097_00002-00142_00001" : { + "minimal_similarity" : 0.4576271186440678, + "maximum_similarity" : 0.5094339622641509, + "matched_token_number" : 54 + }, + "00000_00003-00095_00003" : { + "minimal_similarity" : 0.3023255813953488, + "maximum_similarity" : 0.4369747899159664, + "matched_token_number" : 52 + }, + "00127_00002-00177_00003" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00113_00002-00199_00001" : { + "minimal_similarity" : 0.5163934426229508, + "maximum_similarity" : 0.6631578947368421, + "matched_token_number" : 63 + }, + "00031_00003-00192_00002" : { + "minimal_similarity" : 0.45038167938931295, + "maximum_similarity" : 0.6941176470588235, + "matched_token_number" : 59 + }, + "00192_00002-00195_00002" : { + "minimal_similarity" : 0.4580152671755725, + "maximum_similarity" : 0.5084745762711864, + "matched_token_number" : 60 + }, + "00145_00001-00192_00001" : { + "minimal_similarity" : 0.44516129032258067, + "maximum_similarity" : 0.5609756097560976, + "matched_token_number" : 69 + }, + "00031_00003-00192_00001" : { + "minimal_similarity" : 0.32903225806451614, + "maximum_similarity" : 0.6, + "matched_token_number" : 51 + }, + "00000_00002-00095_00003" : { + "minimal_similarity" : 0.29651162790697677, + "maximum_similarity" : 0.4434782608695652, + "matched_token_number" : 51 + }, + "00154_00002-00156_00002" : { + "minimal_similarity" : 0.41911764705882354, + "maximum_similarity" : 0.4789915966386555, + "matched_token_number" : 57 + }, + "00192_00002-00195_00001" : { + "minimal_similarity" : 0.4580152671755725, + "maximum_similarity" : 0.5084745762711864, + "matched_token_number" : 60 + }, + "00005_00002-00199_00001" : { + "minimal_similarity" : 0.41875, + "maximum_similarity" : 0.7052631578947368, + "matched_token_number" : 67 + }, + "00154_00002-00156_00003" : { + "minimal_similarity" : 0.41911764705882354, + "maximum_similarity" : 0.4789915966386555, + "matched_token_number" : 57 + }, + "00000_00005-00031_00002" : { + "minimal_similarity" : 0.4083333333333333, + "maximum_similarity" : 0.532608695652174, + "matched_token_number" : 49 + }, + "00000_00005-00031_00003" : { + "minimal_similarity" : 0.39166666666666666, + "maximum_similarity" : 0.5529411764705883, + "matched_token_number" : 47 + }, + "00156_00002-00202_00002" : { + "minimal_similarity" : 0.48226950354609927, + "maximum_similarity" : 0.5, + "matched_token_number" : 68 + }, + "00120_00001-00137_00002" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00097_00002-00201_00001" : { + "minimal_similarity" : 0.3113207547169811, + "maximum_similarity" : 0.3793103448275862, + "matched_token_number" : 33 + }, + "00092_00001-00178_00002" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00133_00001-00147_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00156_00002-00202_00003" : { + "minimal_similarity" : 0.46099290780141844, + "maximum_similarity" : 0.47794117647058826, + "matched_token_number" : 65 + }, + "00156_00003-00202_00002" : { + "minimal_similarity" : 0.48226950354609927, + "maximum_similarity" : 0.5, + "matched_token_number" : 68 + }, + "00156_00003-00202_00003" : { + "minimal_similarity" : 0.46099290780141844, + "maximum_similarity" : 0.47794117647058826, + "matched_token_number" : 65 + }, + "00000_00005-00044_00002" : { + "minimal_similarity" : 0.475, + "maximum_similarity" : 0.5757575757575758, + "matched_token_number" : 57 + }, + "00000_00002-00154_00002" : { + "minimal_similarity" : 0.47058823529411764, + "maximum_similarity" : 0.48695652173913045, + "matched_token_number" : 56 + }, + "00044_00002-00156_00002" : { + "minimal_similarity" : 0.3161764705882353, + "maximum_similarity" : 0.43434343434343436, + "matched_token_number" : 43 + }, + "00126_00002-00145_00001" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00000_00003-00154_00002" : { + "minimal_similarity" : 0.47058823529411764, + "maximum_similarity" : 0.47058823529411764, + "matched_token_number" : 56 + }, + "00044_00002-00156_00003" : { + "minimal_similarity" : 0.3161764705882353, + "maximum_similarity" : 0.43434343434343436, + "matched_token_number" : 43 + }, + "00154_00002-00202_00002" : { + "minimal_similarity" : 0.48226950354609927, + "maximum_similarity" : 0.5714285714285714, + "matched_token_number" : 68 + }, + "00113_00002-00135_00001" : { + "minimal_similarity" : 0.5273972602739726, + "maximum_similarity" : 0.6311475409836066, + "matched_token_number" : 77 + }, + "00154_00002-00202_00003" : { + "minimal_similarity" : 0.44680851063829785, + "maximum_similarity" : 0.5294117647058824, + "matched_token_number" : 63 + }, + "00137_00002-00142_00001" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00000_00001-00044_00002" : { + "minimal_similarity" : 0.5353535353535354, + "maximum_similarity" : 0.5408163265306123, + "matched_token_number" : 53 + }, + "00198_00001-00204_00001" : { + "minimal_similarity" : 0.5789473684210527, + "maximum_similarity" : 0.7333333333333333, + "matched_token_number" : 88 + }, + "00178_00002-00197_00001" : { + "minimal_similarity" : 0.5909090909090909, + "maximum_similarity" : 0.6341463414634146, + "matched_token_number" : 78 + }, + "00142_00001-00194_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 56 + }, + "00129_00008-00177_00003" : { + "minimal_similarity" : 0.3191489361702128, + "maximum_similarity" : 0.6097560975609756, + "matched_token_number" : 75 + }, + "00156_00002-00156_00003" : { + "minimal_similarity" : 0.9264705882352942, + "maximum_similarity" : 0.9264705882352942, + "matched_token_number" : 126 + }, + "00186_00002-00196_00001" : { + "minimal_similarity" : 0.1608832807570978, + "maximum_similarity" : 0.3695652173913043, + "matched_token_number" : 51 + }, + "00000_00005-00125_00001" : { + "minimal_similarity" : 0.4634146341463415, + "maximum_similarity" : 0.475, + "matched_token_number" : 57 + }, + "00095_00003-00192_00002" : { + "minimal_similarity" : 0.4069767441860465, + "maximum_similarity" : 0.5343511450381679, + "matched_token_number" : 70 + }, + "00000_00003-00125_00001" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.47058823529411764, + "matched_token_number" : 56 + }, + "00044_00002-00202_00003" : { + "minimal_similarity" : 0.49645390070921985, + "maximum_similarity" : 0.7070707070707071, + "matched_token_number" : 70 + }, + "00013_00002-00135_00001" : { + "minimal_similarity" : 0.4520547945205479, + "maximum_similarity" : 0.6947368421052632, + "matched_token_number" : 66 + }, + "00044_00002-00202_00002" : { + "minimal_similarity" : 0.49645390070921985, + "maximum_similarity" : 0.7070707070707071, + "matched_token_number" : 70 + }, + "00111_00001-00130_00002" : { + "minimal_similarity" : 0.5609756097560976, + "maximum_similarity" : 0.7931034482758621, + "matched_token_number" : 69 + }, + "00005_00002-00194_00001" : { + "minimal_similarity" : 0.3375, + "maximum_similarity" : 0.5, + "matched_token_number" : 54 + }, + "00095_00003-00155_00001" : { + "minimal_similarity" : 0.29069767441860467, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00160_00001-00197_00001" : { + "minimal_similarity" : 0.625, + "maximum_similarity" : 0.6439393939393939, + "matched_token_number" : 85 + }, + "00000_00001-00138_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5714285714285714, + "matched_token_number" : 56 + }, + "00195_00002-00198_00001" : { + "minimal_similarity" : 0.3881578947368421, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00014_00001-00145_00001" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00095_00003-00192_00001" : { + "minimal_similarity" : 0.4011627906976744, + "maximum_similarity" : 0.44516129032258067, + "matched_token_number" : 69 + }, + "00077_00001-00203_00002" : { + "minimal_similarity" : 0.48125, + "maximum_similarity" : 0.5620437956204379, + "matched_token_number" : 77 + }, + "00000_00002-00031_00003" : { + "minimal_similarity" : 0.45217391304347826, + "maximum_similarity" : 0.611764705882353, + "matched_token_number" : 52 + }, + "00138_00001-00153_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00197_00001-00202_00003" : { + "minimal_similarity" : 0.8368794326241135, + "maximum_similarity" : 0.8939393939393939, + "matched_token_number" : 118 + }, + "00131_00005-00147_00001" : { + "minimal_similarity" : 0.45625, + "maximum_similarity" : 0.6186440677966102, + "matched_token_number" : 73 + }, + "00134_00001-00204_00001" : { + "minimal_similarity" : 0.35, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 42 + }, + "00113_00002-00130_00002" : { + "minimal_similarity" : 0.5655737704918032, + "maximum_similarity" : 0.7931034482758621, + "matched_token_number" : 69 + }, + "00136_00002-00204_00001" : { + "minimal_similarity" : 0.35555555555555557, + "maximum_similarity" : 0.5333333333333333, + "matched_token_number" : 64 + }, + "00187_00001-00202_00002" : { + "minimal_similarity" : 0.8156028368794326, + "maximum_similarity" : 0.8712121212121212, + "matched_token_number" : 115 + }, + "00000_00002-00031_00002" : { + "minimal_similarity" : 0.43478260869565216, + "maximum_similarity" : 0.5434782608695652, + "matched_token_number" : 50 + }, + "00187_00001-00202_00003" : { + "minimal_similarity" : 0.8368794326241135, + "maximum_similarity" : 0.8939393939393939, + "matched_token_number" : 118 + }, + "00197_00001-00202_00002" : { + "minimal_similarity" : 0.8156028368794326, + "maximum_similarity" : 0.8712121212121212, + "matched_token_number" : 115 + }, + "00121_00001-00147_00001" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00000_00005-00138_00001" : { + "minimal_similarity" : 0.38333333333333336, + "maximum_similarity" : 0.3898305084745763, + "matched_token_number" : 46 + }, + "00130_00002-00178_00002" : { + "minimal_similarity" : 0.5609756097560976, + "maximum_similarity" : 0.7931034482758621, + "matched_token_number" : 69 + }, + "00153_00001-00196_00001" : { + "minimal_similarity" : 0.17034700315457413, + "maximum_similarity" : 0.43902439024390244, + "matched_token_number" : 54 + }, + "00005_00002-00013_00002" : { + "minimal_similarity" : 0.34375, + "maximum_similarity" : 0.5789473684210527, + "matched_token_number" : 55 + }, + "00000_00002-00192_00002" : { + "minimal_similarity" : 0.4122137404580153, + "maximum_similarity" : 0.46956521739130436, + "matched_token_number" : 54 + }, + "00000_00002-00192_00001" : { + "minimal_similarity" : 0.3548387096774194, + "maximum_similarity" : 0.4782608695652174, + "matched_token_number" : 55 + }, + "00031_00002-00141_00002" : { + "minimal_similarity" : 0.5185185185185185, + "maximum_similarity" : 0.6086956521739131, + "matched_token_number" : 56 + }, + "00129_00008-00202_00002" : { + "minimal_similarity" : 0.39574468085106385, + "maximum_similarity" : 0.6595744680851063, + "matched_token_number" : 93 + }, + "00127_00002-00135_00001" : { + "minimal_similarity" : 0.5273972602739726, + "maximum_similarity" : 0.6260162601626016, + "matched_token_number" : 77 + }, + "00129_00008-00202_00003" : { + "minimal_similarity" : 0.3829787234042553, + "maximum_similarity" : 0.6382978723404256, + "matched_token_number" : 90 + }, + "00145_00001-00154_00002" : { + "minimal_similarity" : 0.8780487804878049, + "maximum_similarity" : 0.907563025210084, + "matched_token_number" : 108 + }, + "00014_00001-00154_00002" : { + "minimal_similarity" : 0.5714285714285714, + "maximum_similarity" : 0.6296296296296297, + "matched_token_number" : 68 + }, + "00133_00001-00201_00001" : { + "minimal_similarity" : 0.3008130081300813, + "maximum_similarity" : 0.42528735632183906, + "matched_token_number" : 37 + }, + "00134_00001-00153_00001" : { + "minimal_similarity" : 0.4715447154471545, + "maximum_similarity" : 0.7160493827160493, + "matched_token_number" : 58 + }, + "00111_00001-00178_00002" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00095_00003-00134_00001" : { + "minimal_similarity" : 0.27325581395348836, + "maximum_similarity" : 0.5802469135802469, + "matched_token_number" : 47 + }, + "00031_00002-00200_00002" : { + "minimal_similarity" : 0.43410852713178294, + "maximum_similarity" : 0.6086956521739131, + "matched_token_number" : 56 + }, + "00031_00003-00125_00001" : { + "minimal_similarity" : 0.43902439024390244, + "maximum_similarity" : 0.6352941176470588, + "matched_token_number" : 54 + }, + "00000_00002-00133_00001" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.48695652173913045, + "matched_token_number" : 56 + }, + "00000_00005-00196_00001" : { + "minimal_similarity" : 0.1861198738170347, + "maximum_similarity" : 0.49166666666666664, + "matched_token_number" : 59 + }, + "00133_00001-00142_00001" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00120_00001-00204_00001" : { + "minimal_similarity" : 0.4666666666666667, + "maximum_similarity" : 0.4745762711864407, + "matched_token_number" : 56 + }, + "00194_00001-00204_00001" : { + "minimal_similarity" : 0.475, + "maximum_similarity" : 0.5277777777777778, + "matched_token_number" : 57 + }, + "00113_00002-00127_00002" : { + "minimal_similarity" : 0.943089430894309, + "maximum_similarity" : 0.9508196721311475, + "matched_token_number" : 116 + }, + "00113_00002-00160_00001" : { + "minimal_similarity" : 0.6102941176470589, + "maximum_similarity" : 0.680327868852459, + "matched_token_number" : 83 + }, + "00142_00001-00186_00002" : { + "minimal_similarity" : 0.3695652173913043, + "maximum_similarity" : 0.4322033898305085, + "matched_token_number" : 51 + }, + "00095_00003-00133_00001" : { + "minimal_similarity" : 0.42441860465116277, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00031_00002-00138_00001" : { + "minimal_similarity" : 0.4067796610169492, + "maximum_similarity" : 0.5217391304347826, + "matched_token_number" : 48 + }, + "00120_00001-00145_00001" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00000_00005-00197_00001" : { + "minimal_similarity" : 0.44696969696969696, + "maximum_similarity" : 0.49166666666666664, + "matched_token_number" : 59 + }, + "00147_00001-00197_00001" : { + "minimal_similarity" : 0.48484848484848486, + "maximum_similarity" : 0.5423728813559322, + "matched_token_number" : 64 + }, + "00014_00001-00153_00001" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00142_00001-00186_00004" : { + "minimal_similarity" : 0.423728813559322, + "maximum_similarity" : 0.4716981132075472, + "matched_token_number" : 50 + }, + "00145_00001-00184_00002" : { + "minimal_similarity" : 0.5203252032520326, + "maximum_similarity" : 0.6808510638297872, + "matched_token_number" : 64 + }, + "00111_00001-00177_00003" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00097_00002-00134_00001" : { + "minimal_similarity" : 0.46226415094339623, + "maximum_similarity" : 0.6049382716049383, + "matched_token_number" : 49 + }, + "00193_00001-00201_00001" : { + "minimal_similarity" : 0.2857142857142857, + "maximum_similarity" : 0.4367816091954023, + "matched_token_number" : 38 + }, + "00140_00001-00203_00002" : { + "minimal_similarity" : 0.38686131386861317, + "maximum_similarity" : 0.6091954022988506, + "matched_token_number" : 53 + }, + "00125_00001-00156_00003" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00125_00001-00156_00002" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00092_00001-00186_00002" : { + "minimal_similarity" : 0.3695652173913043, + "maximum_similarity" : 0.4322033898305085, + "matched_token_number" : 51 + }, + "00121_00001-00177_00003" : { + "minimal_similarity" : 0.6985294117647058, + "maximum_similarity" : 0.7723577235772358, + "matched_token_number" : 95 + }, + "00092_00001-00186_00004" : { + "minimal_similarity" : 0.423728813559322, + "maximum_similarity" : 0.4716981132075472, + "matched_token_number" : 50 + }, + "00031_00002-00201_00001" : { + "minimal_similarity" : 0.25, + "maximum_similarity" : 0.26436781609195403, + "matched_token_number" : 23 + }, + "00031_00003-00044_00002" : { + "minimal_similarity" : 0.5050505050505051, + "maximum_similarity" : 0.5882352941176471, + "matched_token_number" : 50 + }, + "00119_00001-00186_00002" : { + "minimal_similarity" : 0.39855072463768115, + "maximum_similarity" : 0.5092592592592593, + "matched_token_number" : 55 + }, + "00141_00002-00200_00002" : { + "minimal_similarity" : 0.5193798449612403, + "maximum_similarity" : 0.6203703703703703, + "matched_token_number" : 67 + }, + "00119_00001-00186_00004" : { + "minimal_similarity" : 0.49074074074074076, + "maximum_similarity" : 0.5, + "matched_token_number" : 53 + }, + "00177_00003-00203_00002" : { + "minimal_similarity" : 0.5766423357664233, + "maximum_similarity" : 0.6422764227642277, + "matched_token_number" : 79 + }, + "00135_00001-00184_00002" : { + "minimal_similarity" : 0.4246575342465753, + "maximum_similarity" : 0.6595744680851063, + "matched_token_number" : 62 + }, + "00145_00001-00184_00003" : { + "minimal_similarity" : 0.5203252032520326, + "maximum_similarity" : 0.6808510638297872, + "matched_token_number" : 64 + }, + "00135_00001-00184_00003" : { + "minimal_similarity" : 0.4246575342465753, + "maximum_similarity" : 0.6595744680851063, + "matched_token_number" : 62 + }, + "00147_00001-00155_00001" : { + "minimal_similarity" : 0.3220338983050847, + "maximum_similarity" : 0.4367816091954023, + "matched_token_number" : 38 + }, + "00153_00001-00154_00002" : { + "minimal_similarity" : 0.8780487804878049, + "maximum_similarity" : 0.907563025210084, + "matched_token_number" : 108 + }, + "00126_00002-00141_00002" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 56 + }, + "00131_00005-00133_00001" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00129_00008-00186_00004" : { + "minimal_similarity" : 0.22127659574468084, + "maximum_similarity" : 0.49056603773584906, + "matched_token_number" : 52 + }, + "00129_00008-00186_00002" : { + "minimal_similarity" : 0.32340425531914896, + "maximum_similarity" : 0.5507246376811594, + "matched_token_number" : 76 + }, + "00125_00001-00147_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00137_00002-00177_00003" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00193_00001-00202_00003" : { + "minimal_similarity" : 0.5886524822695035, + "maximum_similarity" : 0.6240601503759399, + "matched_token_number" : 83 + }, + "00197_00001-00201_00001" : { + "minimal_similarity" : 0.29545454545454547, + "maximum_similarity" : 0.4482758620689655, + "matched_token_number" : 39 + }, + "00193_00001-00202_00002" : { + "minimal_similarity" : 0.5531914893617021, + "maximum_similarity" : 0.5864661654135338, + "matched_token_number" : 78 + }, + "00000_00005-00129_00008" : { + "minimal_similarity" : 0.28085106382978725, + "maximum_similarity" : 0.55, + "matched_token_number" : 66 + }, + "00137_00002-00184_00003" : { + "minimal_similarity" : 0.5203252032520326, + "maximum_similarity" : 0.6808510638297872, + "matched_token_number" : 64 + }, + "00031_00003-00196_00001" : { + "minimal_similarity" : 0.10725552050473186, + "maximum_similarity" : 0.4, + "matched_token_number" : 34 + }, + "00160_00001-00198_00001" : { + "minimal_similarity" : 0.48026315789473684, + "maximum_similarity" : 0.5367647058823529, + "matched_token_number" : 73 + }, + "00137_00002-00184_00002" : { + "minimal_similarity" : 0.5203252032520326, + "maximum_similarity" : 0.6808510638297872, + "matched_token_number" : 64 + }, + "00095_00003-00120_00001" : { + "minimal_similarity" : 0.36046511627906974, + "maximum_similarity" : 0.5254237288135594, + "matched_token_number" : 62 + }, + "00126_00002-00204_00001" : { + "minimal_similarity" : 0.4666666666666667, + "maximum_similarity" : 0.4745762711864407, + "matched_token_number" : 56 + }, + "00195_00002-00197_00001" : { + "minimal_similarity" : 0.4393939393939394, + "maximum_similarity" : 0.4915254237288136, + "matched_token_number" : 58 + }, + "00113_00002-00136_00002" : { + "minimal_similarity" : 0.4, + "maximum_similarity" : 0.5901639344262295, + "matched_token_number" : 72 + }, + "00095_00003-00126_00002" : { + "minimal_similarity" : 0.36046511627906974, + "maximum_similarity" : 0.5254237288135594, + "matched_token_number" : 62 + }, + "00111_00001-00202_00003" : { + "minimal_similarity" : 0.4326241134751773, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00014_00001-00204_00001" : { + "minimal_similarity" : 0.475, + "maximum_similarity" : 0.5277777777777778, + "matched_token_number" : 57 + }, + "00111_00001-00202_00002" : { + "minimal_similarity" : 0.46808510638297873, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00131_00005-00138_00001" : { + "minimal_similarity" : 0.45625, + "maximum_similarity" : 0.6186440677966102, + "matched_token_number" : 73 + }, + "00031_00003-00129_00008" : { + "minimal_similarity" : 0.2, + "maximum_similarity" : 0.5529411764705883, + "matched_token_number" : 47 + }, + "00125_00001-00142_00001" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00127_00002-00147_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00000_00005-00137_00002" : { + "minimal_similarity" : 0.4634146341463415, + "maximum_similarity" : 0.475, + "matched_token_number" : 57 + }, + "00156_00003-00203_00002" : { + "minimal_similarity" : 0.5109489051094891, + "maximum_similarity" : 0.5147058823529411, + "matched_token_number" : 70 + }, + "00111_00001-00203_00002" : { + "minimal_similarity" : 0.5766423357664233, + "maximum_similarity" : 0.6422764227642277, + "matched_token_number" : 79 + }, + "00129_00008-00178_00002" : { + "minimal_similarity" : 0.3191489361702128, + "maximum_similarity" : 0.6097560975609756, + "matched_token_number" : 75 + }, + "00097_00002-00138_00001" : { + "minimal_similarity" : 0.423728813559322, + "maximum_similarity" : 0.4716981132075472, + "matched_token_number" : 50 + }, + "00131_00005-00134_00001" : { + "minimal_similarity" : 0.33125, + "maximum_similarity" : 0.654320987654321, + "matched_token_number" : 53 + }, + "00000_00001-00201_00001" : { + "minimal_similarity" : 0.2653061224489796, + "maximum_similarity" : 0.2988505747126437, + "matched_token_number" : 26 + }, + "00044_00002-00203_00002" : { + "minimal_similarity" : 0.5036496350364964, + "maximum_similarity" : 0.696969696969697, + "matched_token_number" : 69 + }, + "00095_00003-00125_00001" : { + "minimal_similarity" : 0.42441860465116277, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00147_00001-00154_00002" : { + "minimal_similarity" : 0.4957983193277311, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00113_00002-00198_00001" : { + "minimal_similarity" : 0.4342105263157895, + "maximum_similarity" : 0.5409836065573771, + "matched_token_number" : 66 + }, + "00127_00002-00142_00001" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00199_00001-00201_00001" : { + "minimal_similarity" : 0.3473684210526316, + "maximum_similarity" : 0.3793103448275862, + "matched_token_number" : 33 + }, + "00141_00002-00145_00001" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00126_00002-00133_00001" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00154_00002-00155_00001" : { + "minimal_similarity" : 0.5378151260504201, + "maximum_similarity" : 0.735632183908046, + "matched_token_number" : 64 + }, + "00031_00002-00111_00001" : { + "minimal_similarity" : 0.4634146341463415, + "maximum_similarity" : 0.6195652173913043, + "matched_token_number" : 57 + }, + "00000_00001-00137_00002" : { + "minimal_similarity" : 0.43902439024390244, + "maximum_similarity" : 0.5510204081632653, + "matched_token_number" : 54 + }, + "00097_00002-00202_00003" : { + "minimal_similarity" : 0.3829787234042553, + "maximum_similarity" : 0.5094339622641509, + "matched_token_number" : 54 + }, + "00145_00001-00197_00001" : { + "minimal_similarity" : 0.5909090909090909, + "maximum_similarity" : 0.6341463414634146, + "matched_token_number" : 78 + }, + "00097_00002-00202_00002" : { + "minimal_similarity" : 0.375886524822695, + "maximum_similarity" : 0.5, + "matched_token_number" : 53 + }, + "00000_00003-00155_00001" : { + "minimal_similarity" : 0.3865546218487395, + "maximum_similarity" : 0.5287356321839081, + "matched_token_number" : 46 + }, + "00126_00002-00138_00001" : { + "minimal_similarity" : 0.5338983050847458, + "maximum_similarity" : 0.5338983050847458, + "matched_token_number" : 63 + }, + "00097_00002-00147_00001" : { + "minimal_similarity" : 0.423728813559322, + "maximum_similarity" : 0.4716981132075472, + "matched_token_number" : 50 + }, + "00154_00002-00203_00002" : { + "minimal_similarity" : 0.5255474452554745, + "maximum_similarity" : 0.6050420168067226, + "matched_token_number" : 72 + }, + "00000_00002-00125_00001" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.48695652173913045, + "matched_token_number" : 56 + }, + "00044_00002-00147_00001" : { + "minimal_similarity" : 0.3813559322033898, + "maximum_similarity" : 0.45454545454545453, + "matched_token_number" : 45 + }, + "00031_00003-00137_00002" : { + "minimal_similarity" : 0.43902439024390244, + "maximum_similarity" : 0.6352941176470588, + "matched_token_number" : 54 + }, + "00031_00003-00197_00001" : { + "minimal_similarity" : 0.4166666666666667, + "maximum_similarity" : 0.6470588235294118, + "matched_token_number" : 55 + }, + "00031_00002-00147_00001" : { + "minimal_similarity" : 0.4067796610169492, + "maximum_similarity" : 0.5217391304347826, + "matched_token_number" : 48 + }, + "00000_00001-00200_00002" : { + "minimal_similarity" : 0.4728682170542636, + "maximum_similarity" : 0.6224489795918368, + "matched_token_number" : 61 + }, + "00126_00002-00200_00002" : { + "minimal_similarity" : 0.4263565891472868, + "maximum_similarity" : 0.4661016949152542, + "matched_token_number" : 55 + }, + "00133_00001-00154_00002" : { + "minimal_similarity" : 0.8780487804878049, + "maximum_similarity" : 0.907563025210084, + "matched_token_number" : 108 + }, + "00199_00001-00202_00002" : { + "minimal_similarity" : 0.44680851063829785, + "maximum_similarity" : 0.6631578947368421, + "matched_token_number" : 63 + }, + "00131_00005-00202_00003" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.5957446808510638, + "matched_token_number" : 84 + }, + "00199_00001-00202_00003" : { + "minimal_similarity" : 0.4397163120567376, + "maximum_similarity" : 0.6526315789473685, + "matched_token_number" : 62 + }, + "00125_00001-00203_00002" : { + "minimal_similarity" : 0.5766423357664233, + "maximum_similarity" : 0.6422764227642277, + "matched_token_number" : 79 + }, + "00014_00001-00200_00002" : { + "minimal_similarity" : 0.5193798449612403, + "maximum_similarity" : 0.6203703703703703, + "matched_token_number" : 67 + }, + "00077_00001-00113_00002" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6885245901639344, + "matched_token_number" : 84 + }, + "00000_00005-00192_00001" : { + "minimal_similarity" : 0.3741935483870968, + "maximum_similarity" : 0.48333333333333334, + "matched_token_number" : 58 + }, + "00111_00001-00136_00002" : { + "minimal_similarity" : 0.4, + "maximum_similarity" : 0.5853658536585366, + "matched_token_number" : 72 + }, + "00000_00005-00192_00002" : { + "minimal_similarity" : 0.44274809160305345, + "maximum_similarity" : 0.48333333333333334, + "matched_token_number" : 58 + }, + "00183_00004-00203_00002" : { + "minimal_similarity" : 0.5886524822695035, + "maximum_similarity" : 0.6058394160583942, + "matched_token_number" : 83 + }, + "00131_00005-00202_00002" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.5957446808510638, + "matched_token_number" : 84 + }, + "00126_00002-00140_00001" : { + "minimal_similarity" : 0.4406779661016949, + "maximum_similarity" : 0.5977011494252874, + "matched_token_number" : 52 + }, + "00138_00001-00196_00001" : { + "minimal_similarity" : 0.14826498422712933, + "maximum_similarity" : 0.3983050847457627, + "matched_token_number" : 47 + }, + "00125_00001-00201_00001" : { + "minimal_similarity" : 0.3008130081300813, + "maximum_similarity" : 0.42528735632183906, + "matched_token_number" : 37 + }, + "00113_00002-00193_00001" : { + "minimal_similarity" : 0.5413533834586466, + "maximum_similarity" : 0.5901639344262295, + "matched_token_number" : 72 + }, + "00186_00002-00192_00001" : { + "minimal_similarity" : 0.5806451612903226, + "maximum_similarity" : 0.6521739130434783, + "matched_token_number" : 90 + }, + "00000_00001-00140_00001" : { + "minimal_similarity" : 0.5204081632653061, + "maximum_similarity" : 0.5862068965517241, + "matched_token_number" : 51 + }, + "00133_00001-00156_00002" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00186_00002-00192_00002" : { + "minimal_similarity" : 0.5797101449275363, + "maximum_similarity" : 0.6106870229007634, + "matched_token_number" : 80 + }, + "00140_00001-00156_00003" : { + "minimal_similarity" : 0.36764705882352944, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00133_00001-00156_00003" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00198_00001-00200_00002" : { + "minimal_similarity" : 0.4605263157894737, + "maximum_similarity" : 0.5426356589147286, + "matched_token_number" : 70 + }, + "00131_00005-00141_00002" : { + "minimal_similarity" : 0.3375, + "maximum_similarity" : 0.5, + "matched_token_number" : 54 + }, + "00183_00004-00202_00002" : { + "minimal_similarity" : 0.574468085106383, + "maximum_similarity" : 0.574468085106383, + "matched_token_number" : 81 + }, + "00127_00002-00202_00002" : { + "minimal_similarity" : 0.46808510638297873, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00031_00002-00044_00002" : { + "minimal_similarity" : 0.5151515151515151, + "maximum_similarity" : 0.5543478260869565, + "matched_token_number" : 51 + }, + "00014_00001-00187_00001" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.6111111111111112, + "matched_token_number" : 66 + }, + "00140_00001-00156_00002" : { + "minimal_similarity" : 0.36764705882352944, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00183_00004-00202_00003" : { + "minimal_similarity" : 0.5602836879432624, + "maximum_similarity" : 0.5602836879432624, + "matched_token_number" : 79 + }, + "00127_00002-00202_00003" : { + "minimal_similarity" : 0.4326241134751773, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00000_00005-00133_00001" : { + "minimal_similarity" : 0.4634146341463415, + "maximum_similarity" : 0.475, + "matched_token_number" : 57 + }, + "00192_00001-00203_00002" : { + "minimal_similarity" : 0.6903225806451613, + "maximum_similarity" : 0.781021897810219, + "matched_token_number" : 107 + }, + "00138_00001-00195_00001" : { + "minimal_similarity" : 0.5338983050847458, + "maximum_similarity" : 0.5338983050847458, + "matched_token_number" : 63 + }, + "00014_00001-00140_00001" : { + "minimal_similarity" : 0.46296296296296297, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00092_00001-00119_00001" : { + "minimal_similarity" : 0.4152542372881356, + "maximum_similarity" : 0.4537037037037037, + "matched_token_number" : 49 + }, + "00138_00001-00195_00002" : { + "minimal_similarity" : 0.5338983050847458, + "maximum_similarity" : 0.5338983050847458, + "matched_token_number" : 63 + }, + "00126_00002-00137_00002" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00000_00001-00133_00001" : { + "minimal_similarity" : 0.43902439024390244, + "maximum_similarity" : 0.5510204081632653, + "matched_token_number" : 54 + }, + "00113_00002-00195_00001" : { + "minimal_similarity" : 0.5737704918032787, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00119_00001-00204_00001" : { + "minimal_similarity" : 0.475, + "maximum_similarity" : 0.5277777777777778, + "matched_token_number" : 57 + }, + "00113_00002-00195_00002" : { + "minimal_similarity" : 0.5737704918032787, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00031_00003-00138_00001" : { + "minimal_similarity" : 0.4067796610169492, + "maximum_similarity" : 0.5647058823529412, + "matched_token_number" : 48 + }, + "00145_00001-00196_00001" : { + "minimal_similarity" : 0.17034700315457413, + "maximum_similarity" : 0.43902439024390244, + "matched_token_number" : 54 + }, + "00000_00003-00111_00001" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.47058823529411764, + "matched_token_number" : 56 + }, + "00000_00005-00134_00001" : { + "minimal_similarity" : 0.35, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 42 + }, + "00133_00001-00155_00001" : { + "minimal_similarity" : 0.5447154471544715, + "maximum_similarity" : 0.7701149425287356, + "matched_token_number" : 67 + }, + "00131_00005-00142_00001" : { + "minimal_similarity" : 0.46875, + "maximum_similarity" : 0.635593220338983, + "matched_token_number" : 75 + }, + "00095_00003-00121_00001" : { + "minimal_similarity" : 0.46511627906976744, + "maximum_similarity" : 0.5882352941176471, + "matched_token_number" : 80 + }, + "00125_00001-00202_00002" : { + "minimal_similarity" : 0.46808510638297873, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00183_00004-00201_00001" : { + "minimal_similarity" : 0.3900709219858156, + "maximum_similarity" : 0.632183908045977, + "matched_token_number" : 55 + }, + "00125_00001-00202_00003" : { + "minimal_similarity" : 0.4326241134751773, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00127_00002-00203_00002" : { + "minimal_similarity" : 0.5766423357664233, + "maximum_similarity" : 0.6422764227642277, + "matched_token_number" : 79 + }, + "00000_00001-00134_00001" : { + "minimal_similarity" : 0.4489795918367347, + "maximum_similarity" : 0.5432098765432098, + "matched_token_number" : 44 + }, + "00131_00005-00200_00002" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6511627906976745, + "matched_token_number" : 84 + }, + "00126_00002-00136_00002" : { + "minimal_similarity" : 0.2722222222222222, + "maximum_similarity" : 0.4152542372881356, + "matched_token_number" : 49 + }, + "00192_00001-00204_00001" : { + "minimal_similarity" : 0.6258064516129033, + "maximum_similarity" : 0.8083333333333333, + "matched_token_number" : 97 + }, + "00014_00001-00141_00002" : { + "minimal_similarity" : 0.9722222222222222, + "maximum_similarity" : 0.9722222222222222, + "matched_token_number" : 105 + }, + "00138_00001-00194_00001" : { + "minimal_similarity" : 0.4152542372881356, + "maximum_similarity" : 0.4537037037037037, + "matched_token_number" : 49 + }, + "00129_00008-00201_00001" : { + "minimal_similarity" : 0.2170212765957447, + "maximum_similarity" : 0.5862068965517241, + "matched_token_number" : 51 + }, + "00121_00001-00178_00002" : { + "minimal_similarity" : 0.6985294117647058, + "maximum_similarity" : 0.7723577235772358, + "matched_token_number" : 95 + }, + "00077_00001-00147_00001" : { + "minimal_similarity" : 0.45625, + "maximum_similarity" : 0.6186440677966102, + "matched_token_number" : 73 + }, + "00147_00001-00198_00001" : { + "minimal_similarity" : 0.5131578947368421, + "maximum_similarity" : 0.6610169491525424, + "matched_token_number" : 78 + }, + "00092_00001-00111_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00092_00001-00202_00003" : { + "minimal_similarity" : 0.40425531914893614, + "maximum_similarity" : 0.4830508474576271, + "matched_token_number" : 57 + }, + "00121_00001-00203_00002" : { + "minimal_similarity" : 0.5474452554744526, + "maximum_similarity" : 0.5514705882352942, + "matched_token_number" : 75 + }, + "00140_00001-00187_00001" : { + "minimal_similarity" : 0.44696969696969696, + "maximum_similarity" : 0.6781609195402298, + "matched_token_number" : 59 + }, + "00092_00001-00202_00002" : { + "minimal_similarity" : 0.40425531914893614, + "maximum_similarity" : 0.4830508474576271, + "matched_token_number" : 57 + }, + "00154_00002-00184_00002" : { + "minimal_similarity" : 0.4957983193277311, + "maximum_similarity" : 0.6276595744680851, + "matched_token_number" : 59 + }, + "00154_00002-00184_00003" : { + "minimal_similarity" : 0.4957983193277311, + "maximum_similarity" : 0.6276595744680851, + "matched_token_number" : 59 + }, + "00145_00001-00193_00001" : { + "minimal_similarity" : 0.5488721804511278, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00113_00002-00134_00001" : { + "minimal_similarity" : 0.47540983606557374, + "maximum_similarity" : 0.7160493827160493, + "matched_token_number" : 58 + }, + "00092_00001-00177_00003" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00031_00002-00140_00001" : { + "minimal_similarity" : 0.5543478260869565, + "maximum_similarity" : 0.5862068965517241, + "matched_token_number" : 51 + }, + "00153_00001-00197_00001" : { + "minimal_similarity" : 0.5909090909090909, + "maximum_similarity" : 0.6341463414634146, + "matched_token_number" : 78 + }, + "00013_00002-00131_00005" : { + "minimal_similarity" : 0.34375, + "maximum_similarity" : 0.5789473684210527, + "matched_token_number" : 55 + }, + "00127_00002-00201_00001" : { + "minimal_similarity" : 0.3008130081300813, + "maximum_similarity" : 0.42528735632183906, + "matched_token_number" : 37 + }, + "00142_00001-00153_00001" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00120_00001-00178_00002" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00095_00003-00129_00008" : { + "minimal_similarity" : 0.4808510638297872, + "maximum_similarity" : 0.6569767441860465, + "matched_token_number" : 113 + }, + "00141_00002-00147_00001" : { + "minimal_similarity" : 0.4152542372881356, + "maximum_similarity" : 0.4537037037037037, + "matched_token_number" : 49 + }, + "00000_00003-00187_00001" : { + "minimal_similarity" : 0.4090909090909091, + "maximum_similarity" : 0.453781512605042, + "matched_token_number" : 54 + }, + "00186_00004-00201_00001" : { + "minimal_similarity" : 0.3490566037735849, + "maximum_similarity" : 0.42528735632183906, + "matched_token_number" : 37 + }, + "00014_00001-00201_00001" : { + "minimal_similarity" : 0.37037037037037035, + "maximum_similarity" : 0.45977011494252873, + "matched_token_number" : 40 + }, + "00156_00003-00201_00001" : { + "minimal_similarity" : 0.375, + "maximum_similarity" : 0.5862068965517241, + "matched_token_number" : 51 + }, + "00077_00001-00142_00001" : { + "minimal_similarity" : 0.46875, + "maximum_similarity" : 0.635593220338983, + "matched_token_number" : 75 + }, + "00147_00001-00193_00001" : { + "minimal_similarity" : 0.45864661654135336, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00000_00002-00193_00001" : { + "minimal_similarity" : 0.42857142857142855, + "maximum_similarity" : 0.4956521739130435, + "matched_token_number" : 57 + }, + "00014_00001-00184_00002" : { + "minimal_similarity" : 0.5092592592592593, + "maximum_similarity" : 0.5851063829787234, + "matched_token_number" : 55 + }, + "00014_00001-00184_00003" : { + "minimal_similarity" : 0.5092592592592593, + "maximum_similarity" : 0.5851063829787234, + "matched_token_number" : 55 + }, + "00192_00001-00200_00002" : { + "minimal_similarity" : 0.4838709677419355, + "maximum_similarity" : 0.5813953488372093, + "matched_token_number" : 75 + }, + "00097_00002-00200_00002" : { + "minimal_similarity" : 0.46511627906976744, + "maximum_similarity" : 0.5660377358490566, + "matched_token_number" : 60 + }, + "00000_00005-00193_00001" : { + "minimal_similarity" : 0.43609022556390975, + "maximum_similarity" : 0.48333333333333334, + "matched_token_number" : 58 + }, + "00134_00001-00183_00004" : { + "minimal_similarity" : 0.24822695035460993, + "maximum_similarity" : 0.43209876543209874, + "matched_token_number" : 35 + }, + "00156_00002-00184_00003" : { + "minimal_similarity" : 0.38235294117647056, + "maximum_similarity" : 0.5531914893617021, + "matched_token_number" : 52 + }, + "00156_00002-00184_00002" : { + "minimal_similarity" : 0.38235294117647056, + "maximum_similarity" : 0.5531914893617021, + "matched_token_number" : 52 + }, + "00031_00002-00145_00001" : { + "minimal_similarity" : 0.4634146341463415, + "maximum_similarity" : 0.6195652173913043, + "matched_token_number" : 57 + }, + "00186_00002-00195_00001" : { + "minimal_similarity" : 0.3695652173913043, + "maximum_similarity" : 0.4322033898305085, + "matched_token_number" : 51 + }, + "00186_00002-00195_00002" : { + "minimal_similarity" : 0.3695652173913043, + "maximum_similarity" : 0.4322033898305085, + "matched_token_number" : 51 + }, + "00178_00002-00198_00001" : { + "minimal_similarity" : 0.4342105263157895, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00005_00002-00137_00002" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00031_00003-00198_00001" : { + "minimal_similarity" : 0.3355263157894737, + "maximum_similarity" : 0.6, + "matched_token_number" : 51 + }, + "00000_00003-00113_00002" : { + "minimal_similarity" : 0.45901639344262296, + "maximum_similarity" : 0.47058823529411764, + "matched_token_number" : 56 + }, + "00187_00001-00201_00001" : { + "minimal_similarity" : 0.29545454545454547, + "maximum_similarity" : 0.4482758620689655, + "matched_token_number" : 39 + }, + "00000_00003-00153_00001" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.47058823529411764, + "matched_token_number" : 56 + }, + "00153_00001-00192_00002" : { + "minimal_similarity" : 0.5267175572519084, + "maximum_similarity" : 0.5609756097560976, + "matched_token_number" : 69 + }, + "00134_00001-00156_00002" : { + "minimal_similarity" : 0.3602941176470588, + "maximum_similarity" : 0.6049382716049383, + "matched_token_number" : 49 + }, + "00198_00001-00203_00002" : { + "minimal_similarity" : 0.5526315789473685, + "maximum_similarity" : 0.6131386861313869, + "matched_token_number" : 84 + }, + "00153_00001-00192_00001" : { + "minimal_similarity" : 0.44516129032258067, + "maximum_similarity" : 0.5609756097560976, + "matched_token_number" : 69 + }, + "00134_00001-00156_00003" : { + "minimal_similarity" : 0.3602941176470588, + "maximum_similarity" : 0.6049382716049383, + "matched_token_number" : 49 + }, + "00137_00002-00141_00002" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00130_00002-00137_00002" : { + "minimal_similarity" : 0.5609756097560976, + "maximum_similarity" : 0.7931034482758621, + "matched_token_number" : 69 + }, + "00141_00002-00204_00001" : { + "minimal_similarity" : 0.475, + "maximum_similarity" : 0.5277777777777778, + "matched_token_number" : 57 + }, + "00013_00002-00136_00002" : { + "minimal_similarity" : 0.3333333333333333, + "maximum_similarity" : 0.631578947368421, + "matched_token_number" : 60 + }, + "00000_00002-00126_00002" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.48695652173913045, + "matched_token_number" : 56 + }, + "00145_00001-00153_00001" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00196_00001-00203_00002" : { + "minimal_similarity" : 0.21766561514195584, + "maximum_similarity" : 0.5036496350364964, + "matched_token_number" : 69 + }, + "00044_00002-00184_00003" : { + "minimal_similarity" : 0.46464646464646464, + "maximum_similarity" : 0.48936170212765956, + "matched_token_number" : 46 + }, + "00044_00002-00184_00002" : { + "minimal_similarity" : 0.46464646464646464, + "maximum_similarity" : 0.48936170212765956, + "matched_token_number" : 46 + }, + "00129_00008-00142_00001" : { + "minimal_similarity" : 0.2723404255319149, + "maximum_similarity" : 0.5423728813559322, + "matched_token_number" : 64 + }, + "00192_00002-00194_00001" : { + "minimal_similarity" : 0.5190839694656488, + "maximum_similarity" : 0.6296296296296297, + "matched_token_number" : 68 + }, + "00097_00002-00177_00003" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5754716981132075, + "matched_token_number" : 61 + }, + "00140_00001-00153_00001" : { + "minimal_similarity" : 0.5609756097560976, + "maximum_similarity" : 0.7931034482758621, + "matched_token_number" : 69 + }, + "00031_00003-00134_00001" : { + "minimal_similarity" : 0.4470588235294118, + "maximum_similarity" : 0.4691358024691358, + "matched_token_number" : 38 + }, + "00184_00002-00195_00002" : { + "minimal_similarity" : 0.4661016949152542, + "maximum_similarity" : 0.5851063829787234, + "matched_token_number" : 55 + }, + "00184_00002-00195_00001" : { + "minimal_similarity" : 0.4661016949152542, + "maximum_similarity" : 0.5851063829787234, + "matched_token_number" : 55 + }, + "00031_00002-00204_00001" : { + "minimal_similarity" : 0.39166666666666666, + "maximum_similarity" : 0.5108695652173914, + "matched_token_number" : 47 + }, + "00137_00002-00200_00002" : { + "minimal_similarity" : 0.5658914728682171, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00044_00002-00187_00001" : { + "minimal_similarity" : 0.5378787878787878, + "maximum_similarity" : 0.7171717171717171, + "matched_token_number" : 71 + }, + "00194_00001-00203_00002" : { + "minimal_similarity" : 0.48905109489051096, + "maximum_similarity" : 0.6203703703703703, + "matched_token_number" : 67 + }, + "00000_00005-00198_00001" : { + "minimal_similarity" : 0.4276315789473684, + "maximum_similarity" : 0.5416666666666666, + "matched_token_number" : 65 + }, + "00186_00002-00197_00001" : { + "minimal_similarity" : 0.6304347826086957, + "maximum_similarity" : 0.6590909090909091, + "matched_token_number" : 87 + }, + "00126_00002-00178_00002" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00031_00002-00202_00003" : { + "minimal_similarity" : 0.3829787234042553, + "maximum_similarity" : 0.5869565217391305, + "matched_token_number" : 54 + }, + "00155_00001-00192_00001" : { + "minimal_similarity" : 0.34838709677419355, + "maximum_similarity" : 0.6206896551724138, + "matched_token_number" : 54 + }, + "00155_00001-00192_00002" : { + "minimal_similarity" : 0.40458015267175573, + "maximum_similarity" : 0.6091954022988506, + "matched_token_number" : 53 + }, + "00031_00002-00202_00002" : { + "minimal_similarity" : 0.375886524822695, + "maximum_similarity" : 0.5760869565217391, + "matched_token_number" : 53 + }, + "00192_00002-00196_00001" : { + "minimal_similarity" : 0.22082018927444794, + "maximum_similarity" : 0.5343511450381679, + "matched_token_number" : 70 + }, + "00160_00001-00194_00001" : { + "minimal_similarity" : 0.6029411764705882, + "maximum_similarity" : 0.7592592592592593, + "matched_token_number" : 82 + }, + "00142_00001-00155_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.6436781609195402, + "matched_token_number" : 56 + }, + "00178_00002-00193_00001" : { + "minimal_similarity" : 0.5488721804511278, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00134_00001-00154_00002" : { + "minimal_similarity" : 0.48739495798319327, + "maximum_similarity" : 0.7160493827160493, + "matched_token_number" : 58 + }, + "00178_00002-00196_00001" : { + "minimal_similarity" : 0.17034700315457413, + "maximum_similarity" : 0.43902439024390244, + "matched_token_number" : 54 + }, + "00192_00002-00199_00001" : { + "minimal_similarity" : 0.549618320610687, + "maximum_similarity" : 0.7578947368421053, + "matched_token_number" : 72 + }, + "00135_00001-00183_00004" : { + "minimal_similarity" : 0.541095890410959, + "maximum_similarity" : 0.5602836879432624, + "matched_token_number" : 79 + }, + "00092_00001-00200_00002" : { + "minimal_similarity" : 0.40310077519379844, + "maximum_similarity" : 0.4406779661016949, + "matched_token_number" : 52 + }, + "00135_00001-00186_00002" : { + "minimal_similarity" : 0.3835616438356164, + "maximum_similarity" : 0.4057971014492754, + "matched_token_number" : 56 + }, + "00193_00001-00203_00002" : { + "minimal_similarity" : 0.5547445255474452, + "maximum_similarity" : 0.5714285714285714, + "matched_token_number" : 76 + }, + "00193_00001-00200_00002" : { + "minimal_similarity" : 0.518796992481203, + "maximum_similarity" : 0.5348837209302325, + "matched_token_number" : 69 + }, + "00125_00001-00186_00002" : { + "minimal_similarity" : 0.4782608695652174, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00130_00002-00135_00001" : { + "minimal_similarity" : 0.4041095890410959, + "maximum_similarity" : 0.6781609195402298, + "matched_token_number" : 59 + }, + "00097_00002-00141_00002" : { + "minimal_similarity" : 0.5833333333333334, + "maximum_similarity" : 0.5943396226415094, + "matched_token_number" : 63 + }, + "00125_00001-00186_00004" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.5283018867924528, + "matched_token_number" : 56 + }, + "00135_00001-00186_00004" : { + "minimal_similarity" : 0.410958904109589, + "maximum_similarity" : 0.5660377358490566, + "matched_token_number" : 60 + }, + "00127_00002-00178_00002" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00137_00002-00178_00002" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00135_00001-00154_00002" : { + "minimal_similarity" : 0.5205479452054794, + "maximum_similarity" : 0.6386554621848739, + "matched_token_number" : 76 + }, + "00129_00008-00147_00001" : { + "minimal_similarity" : 0.30638297872340425, + "maximum_similarity" : 0.6101694915254238, + "matched_token_number" : 72 + }, + "00000_00001-00014_00001" : { + "minimal_similarity" : 0.5277777777777778, + "maximum_similarity" : 0.5816326530612245, + "matched_token_number" : 57 + }, + "00092_00001-00113_00002" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00000_00005-00195_00002" : { + "minimal_similarity" : 0.49166666666666664, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00000_00005-00195_00001" : { + "minimal_similarity" : 0.49166666666666664, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00031_00002-00142_00001" : { + "minimal_similarity" : 0.4322033898305085, + "maximum_similarity" : 0.5543478260869565, + "matched_token_number" : 51 + }, + "00197_00001-00203_00002" : { + "minimal_similarity" : 0.7518248175182481, + "maximum_similarity" : 0.7803030303030303, + "matched_token_number" : 103 + }, + "00142_00001-00187_00001" : { + "minimal_similarity" : 0.4393939393939394, + "maximum_similarity" : 0.4915254237288136, + "matched_token_number" : 58 + }, + "00145_00001-00155_00001" : { + "minimal_similarity" : 0.5447154471544715, + "maximum_similarity" : 0.7701149425287356, + "matched_token_number" : 67 + }, + "00013_00002-00133_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.6421052631578947, + "matched_token_number" : 61 + }, + "00141_00002-00201_00001" : { + "minimal_similarity" : 0.37037037037037035, + "maximum_similarity" : 0.45977011494252873, + "matched_token_number" : 40 + }, + "00014_00001-00147_00001" : { + "minimal_similarity" : 0.4152542372881356, + "maximum_similarity" : 0.4537037037037037, + "matched_token_number" : 49 + }, + "00077_00001-00145_00001" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00147_00001-00196_00001" : { + "minimal_similarity" : 0.14826498422712933, + "maximum_similarity" : 0.3983050847457627, + "matched_token_number" : 47 + }, + "00154_00002-00186_00004" : { + "minimal_similarity" : 0.48739495798319327, + "maximum_similarity" : 0.5471698113207547, + "matched_token_number" : 58 + }, + "00095_00003-00127_00002" : { + "minimal_similarity" : 0.42441860465116277, + "maximum_similarity" : 0.5934959349593496, + "matched_token_number" : 73 + }, + "00154_00002-00186_00002" : { + "minimal_similarity" : 0.47101449275362317, + "maximum_similarity" : 0.5462184873949579, + "matched_token_number" : 65 + }, + "00129_00008-00203_00002" : { + "minimal_similarity" : 0.3872340425531915, + "maximum_similarity" : 0.6642335766423357, + "matched_token_number" : 91 + }, + "00136_00002-00177_00003" : { + "minimal_similarity" : 0.4, + "maximum_similarity" : 0.5853658536585366, + "matched_token_number" : 72 + }, + "00155_00001-00160_00001" : { + "minimal_similarity" : 0.4632352941176471, + "maximum_similarity" : 0.7241379310344828, + "matched_token_number" : 63 + }, + "00119_00001-00187_00001" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.6111111111111112, + "matched_token_number" : 66 + }, + "00187_00001-00204_00001" : { + "minimal_similarity" : 0.7196969696969697, + "maximum_similarity" : 0.7916666666666666, + "matched_token_number" : 95 + }, + "00044_00002-00113_00002" : { + "minimal_similarity" : 0.45901639344262296, + "maximum_similarity" : 0.5656565656565656, + "matched_token_number" : 56 + }, + "00141_00002-00142_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 56 + }, + "00196_00001-00200_00002" : { + "minimal_similarity" : 0.21766561514195584, + "maximum_similarity" : 0.5348837209302325, + "matched_token_number" : 69 + }, + "00131_00005-00177_00003" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00153_00001-00195_00002" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00184_00002-00192_00002" : { + "minimal_similarity" : 0.5343511450381679, + "maximum_similarity" : 0.7446808510638298, + "matched_token_number" : 70 + }, + "00145_00001-00156_00002" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00154_00002-00187_00001" : { + "minimal_similarity" : 0.5833333333333334, + "maximum_similarity" : 0.6470588235294118, + "matched_token_number" : 77 + }, + "00145_00001-00156_00003" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00153_00001-00195_00001" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00135_00001-00156_00003" : { + "minimal_similarity" : 0.5547945205479452, + "maximum_similarity" : 0.5955882352941176, + "matched_token_number" : 81 + }, + "00129_00008-00204_00001" : { + "minimal_similarity" : 0.37872340425531914, + "maximum_similarity" : 0.7416666666666667, + "matched_token_number" : 89 + }, + "00135_00001-00156_00002" : { + "minimal_similarity" : 0.5547945205479452, + "maximum_similarity" : 0.5955882352941176, + "matched_token_number" : 81 + }, + "00184_00002-00192_00001" : { + "minimal_similarity" : 0.432258064516129, + "maximum_similarity" : 0.7127659574468085, + "matched_token_number" : 67 + }, + "00160_00001-00196_00001" : { + "minimal_similarity" : 0.24921135646687698, + "maximum_similarity" : 0.5808823529411765, + "matched_token_number" : 79 + }, + "00092_00001-00140_00001" : { + "minimal_similarity" : 0.423728813559322, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00077_00001-00204_00001" : { + "minimal_similarity" : 0.5125, + "maximum_similarity" : 0.6833333333333333, + "matched_token_number" : 82 + }, + "00120_00001-00203_00002" : { + "minimal_similarity" : 0.45255474452554745, + "maximum_similarity" : 0.5254237288135594, + "matched_token_number" : 62 + }, + "00125_00001-00184_00002" : { + "minimal_similarity" : 0.5203252032520326, + "maximum_similarity" : 0.6808510638297872, + "matched_token_number" : 64 + }, + "00125_00001-00184_00003" : { + "minimal_similarity" : 0.5203252032520326, + "maximum_similarity" : 0.6808510638297872, + "matched_token_number" : 64 + }, + "00138_00001-00154_00002" : { + "minimal_similarity" : 0.4957983193277311, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00077_00001-00177_00003" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00140_00001-00184_00003" : { + "minimal_similarity" : 0.46808510638297873, + "maximum_similarity" : 0.5057471264367817, + "matched_token_number" : 44 + }, + "00140_00001-00184_00002" : { + "minimal_similarity" : 0.46808510638297873, + "maximum_similarity" : 0.5057471264367817, + "matched_token_number" : 44 + }, + "00184_00003-00186_00002" : { + "minimal_similarity" : 0.4057971014492754, + "maximum_similarity" : 0.5957446808510638, + "matched_token_number" : 56 + }, + "00153_00001-00194_00001" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00187_00001-00203_00002" : { + "minimal_similarity" : 0.7518248175182481, + "maximum_similarity" : 0.7803030303030303, + "matched_token_number" : 103 + }, + "00113_00002-00131_00005" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6885245901639344, + "matched_token_number" : 84 + }, + "00121_00001-00200_00002" : { + "minimal_similarity" : 0.5367647058823529, + "maximum_similarity" : 0.5658914728682171, + "matched_token_number" : 73 + }, + "00095_00003-00199_00001" : { + "minimal_similarity" : 0.3313953488372093, + "maximum_similarity" : 0.6, + "matched_token_number" : 57 + }, + "00000_00002-00129_00008" : { + "minimal_similarity" : 0.251063829787234, + "maximum_similarity" : 0.5130434782608696, + "matched_token_number" : 59 + }, + "00077_00001-00202_00003" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.5957446808510638, + "matched_token_number" : 84 + }, + "00005_00002-00135_00001" : { + "minimal_similarity" : 0.45625, + "maximum_similarity" : 0.5, + "matched_token_number" : 73 + }, + "00077_00001-00202_00002" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.5957446808510638, + "matched_token_number" : 84 + }, + "00137_00002-00202_00002" : { + "minimal_similarity" : 0.46808510638297873, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00184_00003-00186_00004" : { + "minimal_similarity" : 0.5094339622641509, + "maximum_similarity" : 0.574468085106383, + "matched_token_number" : 54 + }, + "00137_00002-00202_00003" : { + "minimal_similarity" : 0.4326241134751773, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00092_00001-00147_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 118 + }, + "00000_00002-00000_00005" : { + "minimal_similarity" : 0.8583333333333333, + "maximum_similarity" : 0.8956521739130435, + "matched_token_number" : 103 + }, + "00000_00002-00000_00003" : { + "minimal_similarity" : 0.8991596638655462, + "maximum_similarity" : 0.9304347826086956, + "matched_token_number" : 107 + }, + "00031_00003-00130_00002" : { + "minimal_similarity" : 0.5747126436781609, + "maximum_similarity" : 0.5882352941176471, + "matched_token_number" : 50 + }, + "00184_00002-00199_00001" : { + "minimal_similarity" : 0.9789473684210527, + "maximum_similarity" : 0.9893617021276596, + "matched_token_number" : 93 + }, + "00177_00003-00187_00001" : { + "minimal_similarity" : 0.5909090909090909, + "maximum_similarity" : 0.6341463414634146, + "matched_token_number" : 78 + }, + "00000_00003-00184_00003" : { + "minimal_similarity" : 0.4957983193277311, + "maximum_similarity" : 0.6276595744680851, + "matched_token_number" : 59 + }, + "00142_00001-00156_00002" : { + "minimal_similarity" : 0.34558823529411764, + "maximum_similarity" : 0.3983050847457627, + "matched_token_number" : 47 + }, + "00044_00002-00186_00004" : { + "minimal_similarity" : 0.6037735849056604, + "maximum_similarity" : 0.6464646464646465, + "matched_token_number" : 64 + }, + "00005_00002-00077_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 160 + }, + "00044_00002-00186_00002" : { + "minimal_similarity" : 0.6304347826086957, + "maximum_similarity" : 0.8787878787878788, + "matched_token_number" : 87 + }, + "00142_00001-00156_00003" : { + "minimal_similarity" : 0.34558823529411764, + "maximum_similarity" : 0.3983050847457627, + "matched_token_number" : 47 + }, + "00013_00002-00134_00001" : { + "minimal_similarity" : 0.4842105263157895, + "maximum_similarity" : 0.5679012345679012, + "matched_token_number" : 46 + }, + "00000_00003-00184_00002" : { + "minimal_similarity" : 0.4957983193277311, + "maximum_similarity" : 0.6276595744680851, + "matched_token_number" : 59 + }, + "00092_00001-00141_00002" : { + "minimal_similarity" : 0.4152542372881356, + "maximum_similarity" : 0.4537037037037037, + "matched_token_number" : 49 + }, + "00195_00001-00201_00001" : { + "minimal_similarity" : 0.3389830508474576, + "maximum_similarity" : 0.45977011494252873, + "matched_token_number" : 40 + }, + "00184_00002-00193_00001" : { + "minimal_similarity" : 0.42857142857142855, + "maximum_similarity" : 0.6063829787234043, + "matched_token_number" : 57 + }, + "00136_00002-00178_00002" : { + "minimal_similarity" : 0.4, + "maximum_similarity" : 0.5853658536585366, + "matched_token_number" : 72 + }, + "00000_00005-00005_00002" : { + "minimal_similarity" : 0.3875, + "maximum_similarity" : 0.5166666666666667, + "matched_token_number" : 62 + }, + "00156_00002-00186_00002" : { + "minimal_similarity" : 0.37681159420289856, + "maximum_similarity" : 0.38235294117647056, + "matched_token_number" : 52 + }, + "00196_00001-00201_00001" : { + "minimal_similarity" : 0.19558359621451105, + "maximum_similarity" : 0.7126436781609196, + "matched_token_number" : 62 + }, + "00147_00001-00195_00001" : { + "minimal_similarity" : 0.5338983050847458, + "maximum_similarity" : 0.5338983050847458, + "matched_token_number" : 63 + }, + "00147_00001-00195_00002" : { + "minimal_similarity" : 0.5338983050847458, + "maximum_similarity" : 0.5338983050847458, + "matched_token_number" : 63 + }, + "00155_00001-00194_00001" : { + "minimal_similarity" : 0.5370370370370371, + "maximum_similarity" : 0.6666666666666666, + "matched_token_number" : 58 + }, + "00156_00002-00186_00004" : { + "minimal_similarity" : 0.4411764705882353, + "maximum_similarity" : 0.5660377358490566, + "matched_token_number" : 60 + }, + "00160_00001-00192_00001" : { + "minimal_similarity" : 0.5741935483870968, + "maximum_similarity" : 0.6544117647058824, + "matched_token_number" : 89 + }, + "00160_00001-00192_00002" : { + "minimal_similarity" : 0.6102941176470589, + "maximum_similarity" : 0.6335877862595419, + "matched_token_number" : 83 + }, + "00120_00001-00201_00001" : { + "minimal_similarity" : 0.3389830508474576, + "maximum_similarity" : 0.45977011494252873, + "matched_token_number" : 40 + }, + "00186_00004-00204_00001" : { + "minimal_similarity" : 0.5166666666666667, + "maximum_similarity" : 0.5849056603773585, + "matched_token_number" : 62 + }, + "00133_00001-00186_00002" : { + "minimal_similarity" : 0.4782608695652174, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00133_00001-00186_00004" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.5283018867924528, + "matched_token_number" : 56 + }, + "00092_00001-00142_00001" : { + "minimal_similarity" : 0.5338983050847458, + "maximum_similarity" : 0.5338983050847458, + "matched_token_number" : 63 + }, + "00136_00002-00203_00002" : { + "minimal_similarity" : 0.45555555555555555, + "maximum_similarity" : 0.5985401459854015, + "matched_token_number" : 82 + }, + "00000_00003-00183_00004" : { + "minimal_similarity" : 0.425531914893617, + "maximum_similarity" : 0.5042016806722689, + "matched_token_number" : 60 + }, + "00095_00003-00194_00001" : { + "minimal_similarity" : 0.313953488372093, + "maximum_similarity" : 0.5, + "matched_token_number" : 54 + }, + "00138_00001-00156_00002" : { + "minimal_similarity" : 0.35294117647058826, + "maximum_similarity" : 0.4067796610169492, + "matched_token_number" : 48 + }, + "00138_00001-00156_00003" : { + "minimal_similarity" : 0.35294117647058826, + "maximum_similarity" : 0.4067796610169492, + "matched_token_number" : 48 + }, + "00196_00001-00202_00003" : { + "minimal_similarity" : 0.19242902208201892, + "maximum_similarity" : 0.4326241134751773, + "matched_token_number" : 61 + }, + "00196_00001-00202_00002" : { + "minimal_similarity" : 0.20189274447949526, + "maximum_similarity" : 0.45390070921985815, + "matched_token_number" : 64 + }, + "00155_00001-00193_00001" : { + "minimal_similarity" : 0.3533834586466165, + "maximum_similarity" : 0.5402298850574713, + "matched_token_number" : 47 + }, + "00184_00002-00194_00001" : { + "minimal_similarity" : 0.5092592592592593, + "maximum_similarity" : 0.5851063829787234, + "matched_token_number" : 55 + }, + "00194_00001-00201_00001" : { + "minimal_similarity" : 0.37037037037037035, + "maximum_similarity" : 0.45977011494252873, + "matched_token_number" : 40 + }, + "00077_00001-00178_00002" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00097_00002-00178_00002" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5754716981132075, + "matched_token_number" : 61 + }, + "00136_00002-00202_00002" : { + "minimal_similarity" : 0.4388888888888889, + "maximum_similarity" : 0.5602836879432624, + "matched_token_number" : 79 + }, + "00136_00002-00202_00003" : { + "minimal_similarity" : 0.46111111111111114, + "maximum_similarity" : 0.5886524822695035, + "matched_token_number" : 83 + }, + "00134_00001-00184_00003" : { + "minimal_similarity" : 0.46808510638297873, + "maximum_similarity" : 0.5432098765432098, + "matched_token_number" : 44 + }, + "00135_00001-00153_00001" : { + "minimal_similarity" : 0.5273972602739726, + "maximum_similarity" : 0.6260162601626016, + "matched_token_number" : 77 + }, + "00186_00004-00203_00002" : { + "minimal_similarity" : 0.49635036496350365, + "maximum_similarity" : 0.6415094339622641, + "matched_token_number" : 68 + }, + "00095_00003-00193_00001" : { + "minimal_similarity" : 0.36046511627906974, + "maximum_similarity" : 0.46616541353383456, + "matched_token_number" : 62 + }, + "00120_00001-00142_00001" : { + "minimal_similarity" : 0.9830508474576272, + "maximum_similarity" : 0.9830508474576272, + "matched_token_number" : 116 + }, + "00136_00002-00145_00001" : { + "minimal_similarity" : 0.4, + "maximum_similarity" : 0.5853658536585366, + "matched_token_number" : 72 + }, + "00147_00001-00194_00001" : { + "minimal_similarity" : 0.4152542372881356, + "maximum_similarity" : 0.4537037037037037, + "matched_token_number" : 49 + }, + "00120_00001-00200_00002" : { + "minimal_similarity" : 0.4263565891472868, + "maximum_similarity" : 0.4661016949152542, + "matched_token_number" : 55 + }, + "00077_00001-00201_00001" : { + "minimal_similarity" : 0.24375, + "maximum_similarity" : 0.4482758620689655, + "matched_token_number" : 39 + }, + "00194_00001-00202_00003" : { + "minimal_similarity" : 0.45390070921985815, + "maximum_similarity" : 0.5925925925925926, + "matched_token_number" : 64 + }, + "00134_00001-00184_00002" : { + "minimal_similarity" : 0.46808510638297873, + "maximum_similarity" : 0.5432098765432098, + "matched_token_number" : 44 + }, + "00194_00001-00202_00002" : { + "minimal_similarity" : 0.475177304964539, + "maximum_similarity" : 0.6203703703703703, + "matched_token_number" : 67 + }, + "00155_00001-00199_00001" : { + "minimal_similarity" : 0.5052631578947369, + "maximum_similarity" : 0.5517241379310345, + "matched_token_number" : 48 + }, + "00005_00002-00136_00002" : { + "minimal_similarity" : 0.4722222222222222, + "maximum_similarity" : 0.53125, + "matched_token_number" : 85 + }, + "00005_00002-00130_00002" : { + "minimal_similarity" : 0.3375, + "maximum_similarity" : 0.6206896551724138, + "matched_token_number" : 54 + }, + "00119_00001-00183_00004" : { + "minimal_similarity" : 0.425531914893617, + "maximum_similarity" : 0.5555555555555556, + "matched_token_number" : 60 + }, + "00013_00002-00077_00001" : { + "minimal_similarity" : 0.34375, + "maximum_similarity" : 0.5789473684210527, + "matched_token_number" : 55 + }, + "00160_00001-00193_00001" : { + "minimal_similarity" : 0.5735294117647058, + "maximum_similarity" : 0.5864661654135338, + "matched_token_number" : 78 + }, + "00141_00002-00178_00002" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00031_00002-00177_00003" : { + "minimal_similarity" : 0.4634146341463415, + "maximum_similarity" : 0.6195652173913043, + "matched_token_number" : 57 + }, + "00155_00001-00195_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.6436781609195402, + "matched_token_number" : 56 + }, + "00195_00001-00200_00002" : { + "minimal_similarity" : 0.4263565891472868, + "maximum_similarity" : 0.4661016949152542, + "matched_token_number" : 55 + }, + "00136_00002-00201_00001" : { + "minimal_similarity" : 0.2111111111111111, + "maximum_similarity" : 0.4367816091954023, + "matched_token_number" : 38 + }, + "00133_00001-00184_00003" : { + "minimal_similarity" : 0.5203252032520326, + "maximum_similarity" : 0.6808510638297872, + "matched_token_number" : 64 + }, + "00133_00001-00184_00002" : { + "minimal_similarity" : 0.5203252032520326, + "maximum_similarity" : 0.6808510638297872, + "matched_token_number" : 64 + }, + "00155_00001-00195_00002" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.6436781609195402, + "matched_token_number" : 56 + }, + "00177_00003-00186_00004" : { + "minimal_similarity" : 0.45528455284552843, + "maximum_similarity" : 0.5283018867924528, + "matched_token_number" : 56 + }, + "00000_00002-00195_00002" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.48695652173913045, + "matched_token_number" : 56 + }, + "00000_00002-00198_00001" : { + "minimal_similarity" : 0.4144736842105263, + "maximum_similarity" : 0.5478260869565217, + "matched_token_number" : 63 + }, + "00000_00002-00195_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.48695652173913045, + "matched_token_number" : 56 + }, + "00120_00001-00141_00002" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5185185185185185, + "matched_token_number" : 56 + }, + "00177_00003-00186_00002" : { + "minimal_similarity" : 0.4782608695652174, + "maximum_similarity" : 0.5365853658536586, + "matched_token_number" : 66 + }, + "00186_00004-00202_00003" : { + "minimal_similarity" : 0.425531914893617, + "maximum_similarity" : 0.5660377358490566, + "matched_token_number" : 60 + }, + "00186_00004-00202_00002" : { + "minimal_similarity" : 0.41843971631205673, + "maximum_similarity" : 0.5566037735849056, + "matched_token_number" : 59 + }, + "00121_00001-00141_00002" : { + "minimal_similarity" : 0.49264705882352944, + "maximum_similarity" : 0.6203703703703703, + "matched_token_number" : 67 + }, + "00095_00003-00195_00002" : { + "minimal_similarity" : 0.36046511627906974, + "maximum_similarity" : 0.5254237288135594, + "matched_token_number" : 62 + }, + "00095_00003-00195_00001" : { + "minimal_similarity" : 0.36046511627906974, + "maximum_similarity" : 0.5254237288135594, + "matched_token_number" : 62 + }, + "00120_00001-00177_00003" : { + "minimal_similarity" : 0.5691056910569106, + "maximum_similarity" : 0.5932203389830508, + "matched_token_number" : 70 + }, + "00005_00002-00134_00001" : { + "minimal_similarity" : 0.33125, + "maximum_similarity" : 0.654320987654321, + "matched_token_number" : 53 + }, + "00155_00001-00198_00001" : { + "minimal_similarity" : 0.28289473684210525, + "maximum_similarity" : 0.4942528735632184, + "matched_token_number" : 43 + }, + "00195_00001-00203_00002" : { + "minimal_similarity" : 0.45255474452554745, + "maximum_similarity" : 0.5254237288135594, + "matched_token_number" : 62 + }, + "00077_00001-00140_00001" : { + "minimal_similarity" : 0.3375, + "maximum_similarity" : 0.6206896551724138, + "matched_token_number" : 54 + }, + "00137_00002-00201_00001" : { + "minimal_similarity" : 0.3008130081300813, + "maximum_similarity" : 0.42528735632183906, + "matched_token_number" : 37 + }, + "00092_00001-00145_00001" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00136_00002-00140_00001" : { + "minimal_similarity" : 0.29444444444444445, + "maximum_similarity" : 0.6091954022988506, + "matched_token_number" : 53 + }, + "00095_00003-00198_00001" : { + "minimal_similarity" : 0.4186046511627907, + "maximum_similarity" : 0.47368421052631576, + "matched_token_number" : 72 + }, + "00184_00002-00197_00001" : { + "minimal_similarity" : 0.5227272727272727, + "maximum_similarity" : 0.7340425531914894, + "matched_token_number" : 69 + }, + "00156_00003-00178_00002" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00005_00002-00131_00005" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 160 + }, + "00000_00005-00160_00001" : { + "minimal_similarity" : 0.45588235294117646, + "maximum_similarity" : 0.5166666666666667, + "matched_token_number" : 62 + }, + "00178_00002-00199_00001" : { + "minimal_similarity" : 0.5121951219512195, + "maximum_similarity" : 0.6631578947368421, + "matched_token_number" : 63 + }, + "00121_00001-00202_00003" : { + "minimal_similarity" : 0.5035460992907801, + "maximum_similarity" : 0.5220588235294118, + "matched_token_number" : 71 + }, + "00130_00002-00138_00001" : { + "minimal_similarity" : 0.423728813559322, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00140_00001-00186_00002" : { + "minimal_similarity" : 0.38405797101449274, + "maximum_similarity" : 0.6091954022988506, + "matched_token_number" : 53 + }, + "00121_00001-00202_00002" : { + "minimal_similarity" : 0.5035460992907801, + "maximum_similarity" : 0.5220588235294118, + "matched_token_number" : 71 + }, + "00140_00001-00186_00004" : { + "minimal_similarity" : 0.4716981132075472, + "maximum_similarity" : 0.5747126436781609, + "matched_token_number" : 50 + }, + "00177_00003-00183_00004" : { + "minimal_similarity" : 0.48226950354609927, + "maximum_similarity" : 0.5528455284552846, + "matched_token_number" : 68 + }, + "00092_00001-00203_00002" : { + "minimal_similarity" : 0.46715328467153283, + "maximum_similarity" : 0.5423728813559322, + "matched_token_number" : 64 + }, + "00194_00001-00200_00002" : { + "minimal_similarity" : 0.5193798449612403, + "maximum_similarity" : 0.6203703703703703, + "matched_token_number" : 67 + }, + "00140_00001-00183_00004" : { + "minimal_similarity" : 0.3829787234042553, + "maximum_similarity" : 0.6206896551724138, + "matched_token_number" : 54 + }, + "00137_00002-00145_00001" : { + "minimal_similarity" : 0.9512195121951219, + "maximum_similarity" : 0.9512195121951219, + "matched_token_number" : 117 + }, + "00005_00002-00133_00001" : { + "minimal_similarity" : 0.525, + "maximum_similarity" : 0.6829268292682927, + "matched_token_number" : 84 + }, + "00013_00002-00137_00002" : { + "minimal_similarity" : 0.4959349593495935, + "maximum_similarity" : 0.6421052631578947, + "matched_token_number" : 61 + }, + "00092_00001-00204_00001" : { + "minimal_similarity" : 0.5, + "maximum_similarity" : 0.5084745762711864, + "matched_token_number" : 60 + }, + "00195_00001-00202_00003" : { + "minimal_similarity" : 0.41843971631205673, + "maximum_similarity" : 0.5, + "matched_token_number" : 59 + }, + "00095_00003-00197_00001" : { + "minimal_similarity" : 0.37209302325581395, + "maximum_similarity" : 0.48484848484848486, + "matched_token_number" : 64 + }, + "00195_00001-00202_00002" : { + "minimal_similarity" : 0.4326241134751773, + "maximum_similarity" : 0.5169491525423728, + "matched_token_number" : 61 + }, + "00136_00002-00141_00002" : { + "minimal_similarity" : 0.35555555555555557, + "maximum_similarity" : 0.5925925925925926, + "matched_token_number" : 64 + }, + "00155_00001-00197_00001" : { + "minimal_similarity" : 0.42424242424242425, + "maximum_similarity" : 0.6436781609195402, + "matched_token_number" : 56 + }, + "00177_00003-00184_00002" : { + "minimal_similarity" : 0.5203252032520326, + "maximum_similarity" : 0.6808510638297872, + "matched_token_number" : 64 + }, + "00177_00003-00184_00003" : { + "minimal_similarity" : 0.5203252032520326, + "maximum_similarity" : 0.6808510638297872, + "matched_token_number" : 64 + }, + "00134_00001-00186_00002" : { + "minimal_similarity" : 0.3115942028985507, + "maximum_similarity" : 0.5308641975308642, + "matched_token_number" : 43 + }, + "00000_00002-00196_00001" : { + "minimal_similarity" : 0.17350157728706625, + "maximum_similarity" : 0.4782608695652174, + "matched_token_number" : 55 + }, + "00156_00002-00187_00001" : { + "minimal_similarity" : 0.5367647058823529, + "maximum_similarity" : 0.553030303030303, + "matched_token_number" : 73 + }, + "00134_00001-00186_00004" : { + "minimal_similarity" : 0.41509433962264153, + "maximum_similarity" : 0.5432098765432098, + "matched_token_number" : 44 + }, + "00156_00003-00177_00003" : { + "minimal_similarity" : 0.4485294117647059, + "maximum_similarity" : 0.4959349593495935, + "matched_token_number" : 61 + }, + "00186_00004-00200_00002" : { + "minimal_similarity" : 0.3953488372093023, + "maximum_similarity" : 0.4811320754716981, + "matched_token_number" : 51 + }, + "00121_00001-00201_00001" : { + "minimal_similarity" : 0.3014705882352941, + "maximum_similarity" : 0.47126436781609193, + "matched_token_number" : 41 + }, + "00137_00002-00204_00001" : { + "minimal_similarity" : 0.5447154471544715, + "maximum_similarity" : 0.5583333333333333, + "matched_token_number" : 67 + }, + "00000_00003-00186_00004" : { + "minimal_similarity" : 0.3949579831932773, + "maximum_similarity" : 0.44339622641509435, + "matched_token_number" : 47 + }, + "00000_00003-00186_00002" : { + "minimal_similarity" : 0.43478260869565216, + "maximum_similarity" : 0.5042016806722689, + "matched_token_number" : 60 + }, + "00155_00001-00196_00001" : { + "minimal_similarity" : 0.1167192429022082, + "maximum_similarity" : 0.42528735632183906, + "matched_token_number" : 37 + }, + "00031_00002-00178_00002" : { + "minimal_similarity" : 0.4634146341463415, + "maximum_similarity" : 0.6195652173913043, + "matched_token_number" : 57 + }, + "00136_00002-00200_00002" : { + "minimal_similarity" : 0.45555555555555555, + "maximum_similarity" : 0.6356589147286822, + "matched_token_number" : 82 + }, + "00013_00002-00138_00001" : { + "minimal_similarity" : 0.4745762711864407, + "maximum_similarity" : 0.5894736842105263, + "matched_token_number" : 56 + }, + "00141_00002-00177_00003" : { + "minimal_similarity" : 0.5772357723577236, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00184_00003-00187_00001" : { + "minimal_similarity" : 0.5227272727272727, + "maximum_similarity" : 0.7340425531914894, + "matched_token_number" : 69 + }, + "00014_00001-00113_00002" : { + "minimal_similarity" : 0.5819672131147541, + "maximum_similarity" : 0.6574074074074074, + "matched_token_number" : 71 + }, + "00137_00002-00203_00002" : { + "minimal_similarity" : 0.5766423357664233, + "maximum_similarity" : 0.6422764227642277, + "matched_token_number" : 79 + }, + "00184_00002-00198_00001" : { + "minimal_similarity" : 0.40789473684210525, + "maximum_similarity" : 0.6595744680851063, + "matched_token_number" : 62 + }, + "00202_00003-00203_00002" : { + "minimal_similarity" : 0.7163120567375887, + "maximum_similarity" : 0.7372262773722628, + "matched_token_number" : 101 + }, + "00134_00001-00187_00001" : { + "minimal_similarity" : 0.36363636363636365, + "maximum_similarity" : 0.5925925925925926, + "matched_token_number" : 48 + }, + "00095_00003-00196_00001" : { + "minimal_similarity" : 0.2744479495268139, + "maximum_similarity" : 0.5058139534883721, + "matched_token_number" : 87 + }, + "00133_00001-00183_00004" : { + "minimal_similarity" : 0.48226950354609927, + "maximum_similarity" : 0.5528455284552846, + "matched_token_number" : 68 + }, + "00000_00002-00197_00001" : { + "minimal_similarity" : 0.3787878787878788, + "maximum_similarity" : 0.43478260869565216, + "matched_token_number" : 50 + }, + "00121_00001-00142_00001" : { + "minimal_similarity" : 0.4632352941176471, + "maximum_similarity" : 0.5338983050847458, + "matched_token_number" : 63 + }, + "00044_00002-00119_00001" : { + "minimal_similarity" : 0.4537037037037037, + "maximum_similarity" : 0.494949494949495, + "matched_token_number" : 49 + } + }, + "identifier" : "MTM: 3", + "goldStandard" : { + "matchAverage" : 0.9452320735924054, + "nonMatchAverage" : 0.4965832655691376 + } +}, { + "tests" : { + "00113_00002-00141_00002" : { + "minimal_similarity" : 0.2634730538922156, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00092_00001-00197_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00140_00001-00154_00002" : { + "minimal_similarity" : 0.4146341463414634, + "maximum_similarity" : 0.5112781954887218, + "matched_token_number" : 68 + }, + "00013_00002-00129_00008" : { + "minimal_similarity" : 0.11347517730496454, + "maximum_similarity" : 0.24060150375939848, + "matched_token_number" : 32 + }, + "00005_00002-00125_00001" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00147_00001-00178_00002" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00000_00002-00119_00001" : { + "minimal_similarity" : 0.13333333333333333, + "maximum_similarity" : 0.1388888888888889, + "matched_token_number" : 20 + }, + "00119_00001-00125_00001" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00141_00002-00194_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 150 + }, + "00129_00008-00196_00001" : { + "minimal_similarity" : 0.08264462809917356, + "maximum_similarity" : 0.10638297872340426, + "matched_token_number" : 30 + }, + "00135_00001-00195_00002" : { + "minimal_similarity" : 0.04891304347826087, + "maximum_similarity" : 0.058823529411764705, + "matched_token_number" : 9 + }, + "00000_00005-00194_00001" : { + "minimal_similarity" : 0.07333333333333333, + "maximum_similarity" : 0.0738255033557047, + "matched_token_number" : 11 + }, + "00145_00001-00160_00001" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.16176470588235295, + "matched_token_number" : 22 + }, + "00153_00001-00202_00002" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00136_00002-00142_00001" : { + "minimal_similarity" : 0.0547945205479452, + "maximum_similarity" : 0.0784313725490196, + "matched_token_number" : 12 + }, + "00202_00002-00204_00001" : { + "minimal_similarity" : 0.3191489361702128, + "maximum_similarity" : 0.375, + "matched_token_number" : 45 + }, + "00031_00002-00160_00001" : { + "minimal_similarity" : 0.13970588235294118, + "maximum_similarity" : 0.1532258064516129, + "matched_token_number" : 19 + }, + "00135_00001-00195_00001" : { + "minimal_similarity" : 0.04891304347826087, + "maximum_similarity" : 0.058823529411764705, + "matched_token_number" : 9 + }, + "00153_00001-00202_00003" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00000_00003-00199_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00126_00002-00177_00003" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.2482758620689655, + "matched_token_number" : 36 + }, + "00183_00004-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00031_00002-00203_00002" : { + "minimal_similarity" : 0.16551724137931034, + "maximum_similarity" : 0.1935483870967742, + "matched_token_number" : 24 + }, + "00005_00002-00192_00002" : { + "minimal_similarity" : 0.05291005291005291, + "maximum_similarity" : 0.07633587786259542, + "matched_token_number" : 10 + }, + "00177_00003-00192_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.14838709677419354, + "matched_token_number" : 23 + }, + "00005_00002-00192_00001" : { + "minimal_similarity" : 0.05291005291005291, + "maximum_similarity" : 0.06451612903225806, + "matched_token_number" : 10 + }, + "00177_00003-00192_00002" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.1984732824427481, + "matched_token_number" : 26 + }, + "00156_00003-00183_00004" : { + "minimal_similarity" : 0.06741573033707865, + "maximum_similarity" : 0.08163265306122448, + "matched_token_number" : 12 + }, + "00000_00001-00199_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00145_00001-00186_00002" : { + "minimal_similarity" : 0.1534090909090909, + "maximum_similarity" : 0.16071428571428573, + "matched_token_number" : 27 + }, + "00145_00001-00186_00004" : { + "minimal_similarity" : 0.16666666666666666, + "maximum_similarity" : 0.19444444444444445, + "matched_token_number" : 28 + }, + "00125_00001-00137_00002" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00031_00003-00199_00001" : { + "minimal_similarity" : 0.17543859649122806, + "maximum_similarity" : 0.21052631578947367, + "matched_token_number" : 20 + }, + "00138_00001-00147_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 144 + }, + "00134_00001-00142_00001" : { + "minimal_similarity" : 0.16339869281045752, + "maximum_similarity" : 0.21367521367521367, + "matched_token_number" : 25 + }, + "00005_00002-00120_00001" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.13793103448275862, + "matched_token_number" : 20 + }, + "00195_00001-00204_00001" : { + "minimal_similarity" : 0.08496732026143791, + "maximum_similarity" : 0.10833333333333334, + "matched_token_number" : 13 + }, + "00120_00001-00198_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00137_00002-00195_00002" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00137_00002-00195_00001" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00155_00001-00177_00003" : { + "minimal_similarity" : 0.30357142857142855, + "maximum_similarity" : 0.408, + "matched_token_number" : 51 + }, + "00000_00001-00127_00002" : { + "minimal_similarity" : 0.1488095238095238, + "maximum_similarity" : 0.1968503937007874, + "matched_token_number" : 25 + }, + "00031_00002-00119_00001" : { + "minimal_similarity" : 0.07333333333333333, + "maximum_similarity" : 0.08870967741935484, + "matched_token_number" : 11 + }, + "00097_00002-00195_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00097_00002-00195_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00002-00160_00001" : { + "minimal_similarity" : 0.06944444444444445, + "maximum_similarity" : 0.07352941176470588, + "matched_token_number" : 10 + }, + "00127_00002-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00120_00001-00126_00002" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 145 + }, + "00133_00001-00136_00002" : { + "minimal_similarity" : 0.0867579908675799, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00154_00002-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00127_00002-00137_00002" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00014_00001-00202_00002" : { + "minimal_similarity" : 0.14666666666666667, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00000_00005-00199_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00134_00001-00201_00001" : { + "minimal_similarity" : 0.08461538461538462, + "maximum_similarity" : 0.09401709401709402, + "matched_token_number" : 11 + }, + "00184_00003-00202_00002" : { + "minimal_similarity" : 0.14893617021276595, + "maximum_similarity" : 0.22340425531914893, + "matched_token_number" : 21 + }, + "00044_00002-00196_00001" : { + "minimal_similarity" : 0.027548209366391185, + "maximum_similarity" : 0.07352941176470588, + "matched_token_number" : 10 + }, + "00178_00002-00203_00002" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.15862068965517243, + "matched_token_number" : 23 + }, + "00031_00002-00186_00002" : { + "minimal_similarity" : 0.17045454545454544, + "maximum_similarity" : 0.24193548387096775, + "matched_token_number" : 30 + }, + "00184_00003-00202_00003" : { + "minimal_similarity" : 0.14893617021276595, + "maximum_similarity" : 0.22340425531914893, + "matched_token_number" : 21 + }, + "00000_00001-00194_00001" : { + "minimal_similarity" : 0.18, + "maximum_similarity" : 0.2125984251968504, + "matched_token_number" : 27 + }, + "00031_00002-00186_00004" : { + "minimal_similarity" : 0.14583333333333334, + "maximum_similarity" : 0.1693548387096774, + "matched_token_number" : 21 + }, + "00014_00001-00202_00003" : { + "minimal_similarity" : 0.14666666666666667, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00000_00003-00194_00001" : { + "minimal_similarity" : 0.13333333333333333, + "maximum_similarity" : 0.13513513513513514, + "matched_token_number" : 20 + }, + "00119_00001-00120_00001" : { + "minimal_similarity" : 0.31333333333333335, + "maximum_similarity" : 0.32413793103448274, + "matched_token_number" : 47 + }, + "00013_00002-00014_00001" : { + "minimal_similarity" : 0.13333333333333333, + "maximum_similarity" : 0.15037593984962405, + "matched_token_number" : 20 + }, + "00120_00001-00193_00001" : { + "minimal_similarity" : 0.12727272727272726, + "maximum_similarity" : 0.14482758620689656, + "matched_token_number" : 21 + }, + "00126_00002-00156_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00126_00002-00156_00003" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00156_00002-00196_00001" : { + "minimal_similarity" : 0.049586776859504134, + "maximum_similarity" : 0.10112359550561797, + "matched_token_number" : 18 + }, + "00187_00001-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00077_00001-00154_00002" : { + "minimal_similarity" : 0.1111111111111111, + "maximum_similarity" : 0.12804878048780488, + "matched_token_number" : 21 + }, + "00127_00002-00200_00002" : { + "minimal_similarity" : 0.06470588235294118, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00120_00001-00121_00001" : { + "minimal_similarity" : 0.17098445595854922, + "maximum_similarity" : 0.22758620689655173, + "matched_token_number" : 33 + }, + "00192_00001-00193_00001" : { + "minimal_similarity" : 0.11515151515151516, + "maximum_similarity" : 0.12258064516129032, + "matched_token_number" : 19 + }, + "00111_00001-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00119_00001-00141_00002" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 150 + }, + "00031_00003-00127_00002" : { + "minimal_similarity" : 0.14285714285714285, + "maximum_similarity" : 0.21052631578947367, + "matched_token_number" : 24 + }, + "00000_00002-00135_00001" : { + "minimal_similarity" : 0.10869565217391304, + "maximum_similarity" : 0.1388888888888889, + "matched_token_number" : 20 + }, + "00142_00001-00192_00002" : { + "minimal_similarity" : 0.1111111111111111, + "maximum_similarity" : 0.1297709923664122, + "matched_token_number" : 17 + }, + "00142_00001-00192_00001" : { + "minimal_similarity" : 0.08387096774193549, + "maximum_similarity" : 0.08496732026143791, + "matched_token_number" : 13 + }, + "00142_00001-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00130_00002-00192_00002" : { + "minimal_similarity" : 0.12030075187969924, + "maximum_similarity" : 0.12213740458015267, + "matched_token_number" : 16 + }, + "00130_00002-00192_00001" : { + "minimal_similarity" : 0.08387096774193549, + "maximum_similarity" : 0.09774436090225563, + "matched_token_number" : 13 + }, + "00077_00001-00095_00003" : { + "minimal_similarity" : 0.04950495049504951, + "maximum_similarity" : 0.05291005291005291, + "matched_token_number" : 10 + }, + "00133_00001-00187_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.17424242424242425, + "matched_token_number" : 23 + }, + "00130_00002-00155_00001" : { + "minimal_similarity" : 0.39097744360902253, + "maximum_similarity" : 0.416, + "matched_token_number" : 52 + }, + "00147_00001-00199_00001" : { + "minimal_similarity" : 0.06944444444444445, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 10 + }, + "00077_00001-00196_00001" : { + "minimal_similarity" : 0.024793388429752067, + "maximum_similarity" : 0.047619047619047616, + "matched_token_number" : 9 + }, + "00120_00001-00147_00001" : { + "minimal_similarity" : 0.12413793103448276, + "maximum_similarity" : 0.125, + "matched_token_number" : 18 + }, + "00125_00001-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00113_00002-00125_00001" : { + "minimal_similarity" : 0.9940476190476191, + "maximum_similarity" : 1.0, + "matched_token_number" : 167 + }, + "00000_00002-00097_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00013_00002-00044_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00126_00002-00198_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00044_00002-00129_00008" : { + "minimal_similarity" : 0.07801418439716312, + "maximum_similarity" : 0.16176470588235295, + "matched_token_number" : 22 + }, + "00154_00002-00200_00002" : { + "minimal_similarity" : 0.06470588235294118, + "maximum_similarity" : 0.06707317073170732, + "matched_token_number" : 11 + }, + "00178_00002-00195_00001" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00121_00001-00183_00004" : { + "minimal_similarity" : 0.046632124352331605, + "maximum_similarity" : 0.061224489795918366, + "matched_token_number" : 9 + }, + "00186_00002-00199_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00121_00001-00153_00001" : { + "minimal_similarity" : 0.7046632124352331, + "maximum_similarity" : 0.8095238095238095, + "matched_token_number" : 136 + }, + "00092_00001-00192_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00092_00001-00192_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00160_00001-00204_00001" : { + "minimal_similarity" : 0.14705882352941177, + "maximum_similarity" : 0.16666666666666666, + "matched_token_number" : 20 + }, + "00111_00001-00125_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00193_00001-00195_00001" : { + "minimal_similarity" : 0.12727272727272726, + "maximum_similarity" : 0.13725490196078433, + "matched_token_number" : 21 + }, + "00178_00002-00195_00002" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00095_00003-00160_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00193_00001-00195_00002" : { + "minimal_similarity" : 0.12727272727272726, + "maximum_similarity" : 0.13725490196078433, + "matched_token_number" : 21 + }, + "00130_00002-00134_00001" : { + "minimal_similarity" : 0.37593984962406013, + "maximum_similarity" : 0.42735042735042733, + "matched_token_number" : 50 + }, + "00000_00002-00186_00004" : { + "minimal_similarity" : 0.2569444444444444, + "maximum_similarity" : 0.2569444444444444, + "matched_token_number" : 37 + }, + "00119_00001-00192_00001" : { + "minimal_similarity" : 0.08387096774193549, + "maximum_similarity" : 0.08666666666666667, + "matched_token_number" : 13 + }, + "00000_00002-00186_00002" : { + "minimal_similarity" : 0.22727272727272727, + "maximum_similarity" : 0.2777777777777778, + "matched_token_number" : 40 + }, + "00031_00003-00178_00002" : { + "minimal_similarity" : 0.14285714285714285, + "maximum_similarity" : 0.21052631578947367, + "matched_token_number" : 24 + }, + "00119_00001-00192_00002" : { + "minimal_similarity" : 0.11333333333333333, + "maximum_similarity" : 0.1297709923664122, + "matched_token_number" : 17 + }, + "00136_00002-00147_00001" : { + "minimal_similarity" : 0.1004566210045662, + "maximum_similarity" : 0.1527777777777778, + "matched_token_number" : 22 + }, + "00005_00002-00197_00001" : { + "minimal_similarity" : 0.05291005291005291, + "maximum_similarity" : 0.07575757575757576, + "matched_token_number" : 10 + }, + "00156_00003-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00177_00003-00197_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.17424242424242425, + "matched_token_number" : 23 + }, + "00155_00001-00156_00002" : { + "minimal_similarity" : 0.11797752808988764, + "maximum_similarity" : 0.168, + "matched_token_number" : 21 + }, + "00031_00003-00131_00005" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.17543859649122806, + "matched_token_number" : 20 + }, + "00129_00008-00145_00001" : { + "minimal_similarity" : 0.10638297872340426, + "maximum_similarity" : 0.17857142857142858, + "matched_token_number" : 30 + }, + "00126_00002-00130_00002" : { + "minimal_similarity" : 0.18620689655172415, + "maximum_similarity" : 0.20300751879699247, + "matched_token_number" : 27 + }, + "00155_00001-00156_00003" : { + "minimal_similarity" : 0.11797752808988764, + "maximum_similarity" : 0.168, + "matched_token_number" : 21 + }, + "00113_00002-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00140_00001-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00134_00001-00147_00001" : { + "minimal_similarity" : 0.0763888888888889, + "maximum_similarity" : 0.09401709401709402, + "matched_token_number" : 11 + }, + "00138_00001-00177_00003" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00186_00004-00199_00001" : { + "minimal_similarity" : 0.0763888888888889, + "maximum_similarity" : 0.11578947368421053, + "matched_token_number" : 11 + }, + "00192_00002-00197_00001" : { + "minimal_similarity" : 0.49242424242424243, + "maximum_similarity" : 0.4961832061068702, + "matched_token_number" : 65 + }, + "00184_00002-00186_00002" : { + "minimal_similarity" : 0.09659090909090909, + "maximum_similarity" : 0.18085106382978725, + "matched_token_number" : 17 + }, + "00092_00001-00134_00001" : { + "minimal_similarity" : 0.0763888888888889, + "maximum_similarity" : 0.09401709401709402, + "matched_token_number" : 11 + }, + "00183_00004-00204_00001" : { + "minimal_similarity" : 0.061224489795918366, + "maximum_similarity" : 0.075, + "matched_token_number" : 9 + }, + "00184_00002-00186_00004" : { + "minimal_similarity" : 0.1388888888888889, + "maximum_similarity" : 0.2127659574468085, + "matched_token_number" : 20 + }, + "00014_00001-00199_00001" : { + "minimal_similarity" : 0.06666666666666667, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 10 + }, + "00097_00002-00160_00001" : { + "minimal_similarity" : 0.060810810810810814, + "maximum_similarity" : 0.0661764705882353, + "matched_token_number" : 9 + }, + "00131_00005-00153_00001" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00131_00005-00186_00004" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.1388888888888889, + "matched_token_number" : 20 + }, + "00095_00003-00119_00001" : { + "minimal_similarity" : 0.10891089108910891, + "maximum_similarity" : 0.14666666666666667, + "matched_token_number" : 22 + }, + "00119_00001-00200_00002" : { + "minimal_similarity" : 0.058823529411764705, + "maximum_similarity" : 0.06666666666666667, + "matched_token_number" : 10 + }, + "00000_00003-00000_00005" : { + "minimal_similarity" : 0.912751677852349, + "maximum_similarity" : 0.918918918918919, + "matched_token_number" : 136 + }, + "00119_00001-00155_00001" : { + "minimal_similarity" : 0.3933333333333333, + "maximum_similarity" : 0.472, + "matched_token_number" : 59 + }, + "00131_00005-00186_00002" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.11363636363636363, + "matched_token_number" : 20 + }, + "00129_00008-00133_00001" : { + "minimal_similarity" : 0.10638297872340426, + "maximum_similarity" : 0.17857142857142858, + "matched_token_number" : 30 + }, + "00097_00002-00153_00001" : { + "minimal_similarity" : 0.07738095238095238, + "maximum_similarity" : 0.08783783783783784, + "matched_token_number" : 13 + }, + "00000_00002-00013_00002" : { + "minimal_similarity" : 0.0625, + "maximum_similarity" : 0.06766917293233082, + "matched_token_number" : 9 + }, + "00127_00002-00141_00002" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00031_00002-00092_00001" : { + "minimal_similarity" : 0.0763888888888889, + "maximum_similarity" : 0.08870967741935484, + "matched_token_number" : 11 + }, + "00000_00005-00131_00005" : { + "minimal_similarity" : 0.047619047619047616, + "maximum_similarity" : 0.06040268456375839, + "matched_token_number" : 9 + }, + "00184_00003-00199_00001" : { + "minimal_similarity" : 0.9157894736842105, + "maximum_similarity" : 0.925531914893617, + "matched_token_number" : 87 + }, + "00044_00002-00095_00003" : { + "minimal_similarity" : 0.12871287128712872, + "maximum_similarity" : 0.19117647058823528, + "matched_token_number" : 26 + }, + "00113_00002-00197_00001" : { + "minimal_similarity" : 0.1377245508982036, + "maximum_similarity" : 0.17424242424242425, + "matched_token_number" : 23 + }, + "00044_00002-00138_00001" : { + "minimal_similarity" : 0.06944444444444445, + "maximum_similarity" : 0.07352941176470588, + "matched_token_number" : 10 + }, + "00000_00001-00136_00002" : { + "minimal_similarity" : 0.091324200913242, + "maximum_similarity" : 0.15748031496062992, + "matched_token_number" : 20 + }, + "00129_00008-00140_00001" : { + "minimal_similarity" : 0.07801418439716312, + "maximum_similarity" : 0.16541353383458646, + "matched_token_number" : 22 + }, + "00133_00001-00145_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00031_00003-00136_00002" : { + "minimal_similarity" : 0.0867579908675799, + "maximum_similarity" : 0.16666666666666666, + "matched_token_number" : 19 + }, + "00141_00002-00202_00003" : { + "minimal_similarity" : 0.14666666666666667, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00005_00002-00155_00001" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.152, + "matched_token_number" : 19 + }, + "00192_00002-00202_00002" : { + "minimal_similarity" : 0.46808510638297873, + "maximum_similarity" : 0.5038167938931297, + "matched_token_number" : 66 + }, + "00141_00002-00202_00002" : { + "minimal_similarity" : 0.14666666666666667, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00031_00002-00156_00003" : { + "minimal_similarity" : 0.21910112359550563, + "maximum_similarity" : 0.31451612903225806, + "matched_token_number" : 39 + }, + "00014_00001-00194_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 150 + }, + "00031_00002-00156_00002" : { + "minimal_similarity" : 0.21910112359550563, + "maximum_similarity" : 0.31451612903225806, + "matched_token_number" : 39 + }, + "00138_00001-00184_00003" : { + "minimal_similarity" : 0.06944444444444445, + "maximum_similarity" : 0.10638297872340426, + "matched_token_number" : 10 + }, + "00192_00002-00202_00003" : { + "minimal_similarity" : 0.48936170212765956, + "maximum_similarity" : 0.5267175572519084, + "matched_token_number" : 69 + }, + "00044_00002-00204_00001" : { + "minimal_similarity" : 0.17647058823529413, + "maximum_similarity" : 0.2, + "matched_token_number" : 24 + }, + "00000_00001-00202_00002" : { + "minimal_similarity" : 0.23404255319148937, + "maximum_similarity" : 0.25984251968503935, + "matched_token_number" : 33 + }, + "00111_00001-00192_00002" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.1984732824427481, + "matched_token_number" : 26 + }, + "00138_00001-00184_00002" : { + "minimal_similarity" : 0.06944444444444445, + "maximum_similarity" : 0.10638297872340426, + "matched_token_number" : 10 + }, + "00000_00001-00202_00003" : { + "minimal_similarity" : 0.2127659574468085, + "maximum_similarity" : 0.23622047244094488, + "matched_token_number" : 30 + }, + "00111_00001-00192_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.14838709677419354, + "matched_token_number" : 23 + }, + "00183_00004-00187_00001" : { + "minimal_similarity" : 0.07482993197278912, + "maximum_similarity" : 0.08333333333333333, + "matched_token_number" : 11 + }, + "00000_00002-00130_00002" : { + "minimal_similarity" : 0.0625, + "maximum_similarity" : 0.06766917293233082, + "matched_token_number" : 9 + }, + "00031_00003-00077_00001" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.17543859649122806, + "matched_token_number" : 20 + }, + "00126_00002-00186_00004" : { + "minimal_similarity" : 0.1103448275862069, + "maximum_similarity" : 0.1111111111111111, + "matched_token_number" : 16 + }, + "00153_00001-00199_00001" : { + "minimal_similarity" : 0.05952380952380952, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 10 + }, + "00126_00002-00186_00002" : { + "minimal_similarity" : 0.09090909090909091, + "maximum_similarity" : 0.1103448275862069, + "matched_token_number" : 16 + }, + "00160_00001-00199_00001" : { + "minimal_similarity" : 0.0661764705882353, + "maximum_similarity" : 0.09473684210526316, + "matched_token_number" : 9 + }, + "00014_00001-00134_00001" : { + "minimal_similarity" : 0.26, + "maximum_similarity" : 0.3333333333333333, + "matched_token_number" : 39 + }, + "00133_00001-00199_00001" : { + "minimal_similarity" : 0.05952380952380952, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 10 + }, + "00000_00003-00005_00002" : { + "minimal_similarity" : 0.047619047619047616, + "maximum_similarity" : 0.060810810810810814, + "matched_token_number" : 9 + }, + "00127_00002-00153_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00113_00002-00192_00001" : { + "minimal_similarity" : 0.1377245508982036, + "maximum_similarity" : 0.14838709677419354, + "matched_token_number" : 23 + }, + "00133_00001-00204_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.19166666666666668, + "matched_token_number" : 23 + }, + "00044_00002-00145_00001" : { + "minimal_similarity" : 0.16071428571428573, + "maximum_similarity" : 0.19852941176470587, + "matched_token_number" : 27 + }, + "00113_00002-00192_00002" : { + "minimal_similarity" : 0.15568862275449102, + "maximum_similarity" : 0.1984732824427481, + "matched_token_number" : 26 + }, + "00142_00001-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00125_00001-00200_00002" : { + "minimal_similarity" : 0.06470588235294118, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00129_00008-00138_00001" : { + "minimal_similarity" : 0.031914893617021274, + "maximum_similarity" : 0.0625, + "matched_token_number" : 9 + }, + "00125_00001-00153_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00178_00002-00186_00002" : { + "minimal_similarity" : 0.1534090909090909, + "maximum_similarity" : 0.16071428571428573, + "matched_token_number" : 27 + }, + "00000_00001-00131_00005" : { + "minimal_similarity" : 0.06878306878306878, + "maximum_similarity" : 0.10236220472440945, + "matched_token_number" : 13 + }, + "00138_00001-00198_00001" : { + "minimal_similarity" : 0.050505050505050504, + "maximum_similarity" : 0.06944444444444445, + "matched_token_number" : 10 + }, + "00000_00005-00136_00002" : { + "minimal_similarity" : 0.0410958904109589, + "maximum_similarity" : 0.06040268456375839, + "matched_token_number" : 9 + }, + "00178_00002-00186_00004" : { + "minimal_similarity" : 0.16666666666666666, + "maximum_similarity" : 0.19444444444444445, + "matched_token_number" : 28 + }, + "00014_00001-00127_00002" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00192_00001-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00002-00177_00003" : { + "minimal_similarity" : 0.11904761904761904, + "maximum_similarity" : 0.1388888888888889, + "matched_token_number" : 20 + }, + "00125_00001-00141_00002" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00092_00001-00120_00001" : { + "minimal_similarity" : 0.12413793103448276, + "maximum_similarity" : 0.125, + "matched_token_number" : 18 + }, + "00111_00001-00197_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.17424242424242425, + "matched_token_number" : 23 + }, + "00154_00002-00195_00001" : { + "minimal_similarity" : 0.15853658536585366, + "maximum_similarity" : 0.16993464052287582, + "matched_token_number" : 26 + }, + "00136_00002-00156_00003" : { + "minimal_similarity" : 0.1324200913242009, + "maximum_similarity" : 0.16292134831460675, + "matched_token_number" : 29 + }, + "00131_00005-00203_00002" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.13793103448275862, + "matched_token_number" : 20 + }, + "00197_00001-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00154_00002-00195_00002" : { + "minimal_similarity" : 0.15853658536585366, + "maximum_similarity" : 0.16993464052287582, + "matched_token_number" : 26 + }, + "00198_00001-00202_00002" : { + "minimal_similarity" : 0.15151515151515152, + "maximum_similarity" : 0.2127659574468085, + "matched_token_number" : 30 + }, + "00198_00001-00202_00003" : { + "minimal_similarity" : 0.18181818181818182, + "maximum_similarity" : 0.2553191489361702, + "matched_token_number" : 36 + }, + "00031_00003-00202_00002" : { + "minimal_similarity" : 0.22695035460992907, + "maximum_similarity" : 0.2807017543859649, + "matched_token_number" : 32 + }, + "00031_00003-00202_00003" : { + "minimal_similarity" : 0.23404255319148937, + "maximum_similarity" : 0.2894736842105263, + "matched_token_number" : 33 + }, + "00000_00005-00178_00002" : { + "minimal_similarity" : 0.06547619047619048, + "maximum_similarity" : 0.0738255033557047, + "matched_token_number" : 11 + }, + "00031_00003-00187_00001" : { + "minimal_similarity" : 0.26515151515151514, + "maximum_similarity" : 0.30701754385964913, + "matched_token_number" : 35 + }, + "00186_00002-00194_00001" : { + "minimal_similarity" : 0.1534090909090909, + "maximum_similarity" : 0.18, + "matched_token_number" : 27 + }, + "00000_00001-00178_00002" : { + "minimal_similarity" : 0.1488095238095238, + "maximum_similarity" : 0.1968503937007874, + "matched_token_number" : 25 + }, + "00005_00002-00111_00001" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00126_00002-00135_00001" : { + "minimal_similarity" : 0.04891304347826087, + "maximum_similarity" : 0.06206896551724138, + "matched_token_number" : 9 + }, + "00131_00005-00137_00002" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00186_00002-00202_00003" : { + "minimal_similarity" : 0.36363636363636365, + "maximum_similarity" : 0.45390070921985815, + "matched_token_number" : 64 + }, + "00186_00002-00202_00002" : { + "minimal_similarity" : 0.3125, + "maximum_similarity" : 0.3900709219858156, + "matched_token_number" : 55 + }, + "00138_00001-00193_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00119_00001-00197_00001" : { + "minimal_similarity" : 0.08666666666666667, + "maximum_similarity" : 0.09848484848484848, + "matched_token_number" : 13 + }, + "00092_00001-00125_00001" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00113_00002-00200_00002" : { + "minimal_similarity" : 0.06470588235294118, + "maximum_similarity" : 0.0658682634730539, + "matched_token_number" : 11 + }, + "00129_00008-00187_00001" : { + "minimal_similarity" : 0.07446808510638298, + "maximum_similarity" : 0.1590909090909091, + "matched_token_number" : 21 + }, + "00131_00005-00135_00001" : { + "minimal_similarity" : 0.09523809523809523, + "maximum_similarity" : 0.09782608695652174, + "matched_token_number" : 18 + }, + "00131_00005-00195_00002" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.13071895424836602, + "matched_token_number" : 20 + }, + "00000_00001-00077_00001" : { + "minimal_similarity" : 0.06878306878306878, + "maximum_similarity" : 0.10236220472440945, + "matched_token_number" : 13 + }, + "00000_00005-00077_00001" : { + "minimal_similarity" : 0.047619047619047616, + "maximum_similarity" : 0.06040268456375839, + "matched_token_number" : 9 + }, + "00127_00002-00195_00001" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00131_00005-00195_00001" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.13071895424836602, + "matched_token_number" : 20 + }, + "00044_00002-00154_00002" : { + "minimal_similarity" : 0.16463414634146342, + "maximum_similarity" : 0.19852941176470587, + "matched_token_number" : 27 + }, + "00127_00002-00195_00002" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00031_00002-00097_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00120_00001-00156_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00111_00001-00200_00002" : { + "minimal_similarity" : 0.06470588235294118, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00120_00001-00156_00003" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00129_00008-00184_00002" : { + "minimal_similarity" : 0.0425531914893617, + "maximum_similarity" : 0.1276595744680851, + "matched_token_number" : 12 + }, + "00129_00008-00184_00003" : { + "minimal_similarity" : 0.0425531914893617, + "maximum_similarity" : 0.1276595744680851, + "matched_token_number" : 12 + }, + "00000_00005-00127_00002" : { + "minimal_similarity" : 0.06547619047619048, + "maximum_similarity" : 0.0738255033557047, + "matched_token_number" : 11 + }, + "00199_00001-00204_00001" : { + "minimal_similarity" : 0.075, + "maximum_similarity" : 0.09473684210526316, + "matched_token_number" : 9 + }, + "00138_00001-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00138_00001-00142_00001" : { + "minimal_similarity" : 0.11764705882352941, + "maximum_similarity" : 0.125, + "matched_token_number" : 18 + }, + "00125_00001-00195_00002" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00125_00001-00195_00001" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00111_00001-00141_00002" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00141_00002-00199_00001" : { + "minimal_similarity" : 0.06666666666666667, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 10 + }, + "00145_00001-00195_00002" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00097_00002-00203_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00145_00001-00195_00001" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00192_00001-00198_00001" : { + "minimal_similarity" : 0.13131313131313133, + "maximum_similarity" : 0.16774193548387098, + "matched_token_number" : 26 + }, + "00113_00002-00137_00002" : { + "minimal_similarity" : 0.9940476190476191, + "maximum_similarity" : 1.0, + "matched_token_number" : 167 + }, + "00126_00002-00142_00001" : { + "minimal_similarity" : 0.9477124183006536, + "maximum_similarity" : 1.0, + "matched_token_number" : 145 + }, + "00153_00001-00155_00001" : { + "minimal_similarity" : 0.30357142857142855, + "maximum_similarity" : 0.408, + "matched_token_number" : 51 + }, + "00145_00001-00203_00002" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.15862068965517243, + "matched_token_number" : 23 + }, + "00127_00002-00197_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.17424242424242425, + "matched_token_number" : 23 + }, + "00126_00002-00193_00001" : { + "minimal_similarity" : 0.12727272727272726, + "maximum_similarity" : 0.14482758620689656, + "matched_token_number" : 21 + }, + "00031_00003-00194_00001" : { + "minimal_similarity" : 0.16, + "maximum_similarity" : 0.21052631578947367, + "matched_token_number" : 24 + }, + "00111_00001-00137_00002" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00129_00008-00136_00002" : { + "minimal_similarity" : 0.07092198581560284, + "maximum_similarity" : 0.091324200913242, + "matched_token_number" : 20 + }, + "00156_00002-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00097_00002-00130_00002" : { + "minimal_similarity" : 0.25675675675675674, + "maximum_similarity" : 0.2857142857142857, + "matched_token_number" : 38 + }, + "00126_00002-00184_00002" : { + "minimal_similarity" : 0.11724137931034483, + "maximum_similarity" : 0.18085106382978725, + "matched_token_number" : 17 + }, + "00077_00001-00187_00001" : { + "minimal_similarity" : 0.05291005291005291, + "maximum_similarity" : 0.07575757575757576, + "matched_token_number" : 10 + }, + "00126_00002-00184_00003" : { + "minimal_similarity" : 0.11724137931034483, + "maximum_similarity" : 0.18085106382978725, + "matched_token_number" : 17 + }, + "00092_00001-00137_00002" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00135_00001-00200_00002" : { + "minimal_similarity" : 0.05434782608695652, + "maximum_similarity" : 0.058823529411764705, + "matched_token_number" : 10 + }, + "00177_00003-00202_00003" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00140_00001-00147_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00097_00002-00183_00004" : { + "minimal_similarity" : 0.060810810810810814, + "maximum_similarity" : 0.061224489795918366, + "matched_token_number" : 9 + }, + "00031_00003-00140_00001" : { + "minimal_similarity" : 0.10526315789473684, + "maximum_similarity" : 0.12280701754385964, + "matched_token_number" : 14 + }, + "00154_00002-00197_00001" : { + "minimal_similarity" : 0.1402439024390244, + "maximum_similarity" : 0.17424242424242425, + "matched_token_number" : 23 + }, + "00141_00002-00187_00001" : { + "minimal_similarity" : 0.08666666666666667, + "maximum_similarity" : 0.09848484848484848, + "matched_token_number" : 13 + }, + "00013_00002-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00095_00003-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00002-00121_00001" : { + "minimal_similarity" : 0.10362694300518134, + "maximum_similarity" : 0.1388888888888889, + "matched_token_number" : 20 + }, + "00000_00005-00187_00001" : { + "minimal_similarity" : 0.14093959731543623, + "maximum_similarity" : 0.1590909090909091, + "matched_token_number" : 21 + }, + "00177_00003-00202_00002" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00031_00002-00153_00001" : { + "minimal_similarity" : 0.06547619047619048, + "maximum_similarity" : 0.08870967741935484, + "matched_token_number" : 11 + }, + "00044_00002-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00111_00001-00195_00001" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00111_00001-00195_00002" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00183_00004-00184_00003" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00183_00004-00184_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00126_00002-00201_00001" : { + "minimal_similarity" : 0.1310344827586207, + "maximum_similarity" : 0.14615384615384616, + "matched_token_number" : 19 + }, + "00131_00005-00183_00004" : { + "minimal_similarity" : 0.09523809523809523, + "maximum_similarity" : 0.12244897959183673, + "matched_token_number" : 18 + }, + "00119_00001-00153_00001" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00120_00001-00138_00001" : { + "minimal_similarity" : 0.12413793103448276, + "maximum_similarity" : 0.125, + "matched_token_number" : 18 + }, + "00125_00001-00192_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.14838709677419354, + "matched_token_number" : 23 + }, + "00125_00001-00192_00002" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.1984732824427481, + "matched_token_number" : 26 + }, + "00121_00001-00186_00002" : { + "minimal_similarity" : 0.17098445595854922, + "maximum_similarity" : 0.1875, + "matched_token_number" : 33 + }, + "00140_00001-00142_00001" : { + "minimal_similarity" : 0.17647058823529413, + "maximum_similarity" : 0.20300751879699247, + "matched_token_number" : 27 + }, + "00095_00003-00137_00002" : { + "minimal_similarity" : 0.11386138613861387, + "maximum_similarity" : 0.13690476190476192, + "matched_token_number" : 23 + }, + "00184_00002-00184_00003" : { + "minimal_similarity" : 0.9680851063829787, + "maximum_similarity" : 0.9680851063829787, + "matched_token_number" : 91 + }, + "00145_00001-00198_00001" : { + "minimal_similarity" : 0.18686868686868688, + "maximum_similarity" : 0.22023809523809523, + "matched_token_number" : 37 + }, + "00000_00002-00153_00001" : { + "minimal_similarity" : 0.11904761904761904, + "maximum_similarity" : 0.1388888888888889, + "matched_token_number" : 20 + }, + "00119_00001-00202_00003" : { + "minimal_similarity" : 0.14666666666666667, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00121_00001-00186_00004" : { + "minimal_similarity" : 0.17098445595854922, + "maximum_similarity" : 0.22916666666666666, + "matched_token_number" : 33 + }, + "00000_00001-00113_00002" : { + "minimal_similarity" : 0.1497005988023952, + "maximum_similarity" : 0.1968503937007874, + "matched_token_number" : 25 + }, + "00134_00001-00196_00001" : { + "minimal_similarity" : 0.024793388429752067, + "maximum_similarity" : 0.07692307692307693, + "matched_token_number" : 9 + }, + "00119_00001-00202_00002" : { + "minimal_similarity" : 0.14666666666666667, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00140_00001-00193_00001" : { + "minimal_similarity" : 0.07272727272727272, + "maximum_similarity" : 0.09022556390977443, + "matched_token_number" : 12 + }, + "00111_00001-00134_00001" : { + "minimal_similarity" : 0.1488095238095238, + "maximum_similarity" : 0.21367521367521367, + "matched_token_number" : 25 + }, + "00095_00003-00130_00002" : { + "minimal_similarity" : 0.0594059405940594, + "maximum_similarity" : 0.09022556390977443, + "matched_token_number" : 12 + }, + "00138_00001-00186_00002" : { + "minimal_similarity" : 0.056818181818181816, + "maximum_similarity" : 0.06944444444444445, + "matched_token_number" : 10 + }, + "00130_00002-00200_00002" : { + "minimal_similarity" : 0.10588235294117647, + "maximum_similarity" : 0.13533834586466165, + "matched_token_number" : 18 + }, + "00138_00001-00186_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00135_00001-00141_00002" : { + "minimal_similarity" : 0.1956521739130435, + "maximum_similarity" : 0.24, + "matched_token_number" : 36 + }, + "00092_00001-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00003-00145_00001" : { + "minimal_similarity" : 0.11904761904761904, + "maximum_similarity" : 0.13513513513513514, + "matched_token_number" : 20 + }, + "00097_00002-00137_00002" : { + "minimal_similarity" : 0.07738095238095238, + "maximum_similarity" : 0.08783783783783784, + "matched_token_number" : 13 + }, + "00136_00002-00156_00002" : { + "minimal_similarity" : 0.1324200913242009, + "maximum_similarity" : 0.16292134831460675, + "matched_token_number" : 29 + }, + "00126_00002-00203_00002" : { + "minimal_similarity" : 0.15172413793103448, + "maximum_similarity" : 0.15172413793103448, + "matched_token_number" : 22 + }, + "00133_00001-00194_00001" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00137_00002-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00001-00145_00001" : { + "minimal_similarity" : 0.1488095238095238, + "maximum_similarity" : 0.1968503937007874, + "matched_token_number" : 25 + }, + "00195_00002-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00031_00002-00137_00002" : { + "minimal_similarity" : 0.06547619047619048, + "maximum_similarity" : 0.08870967741935484, + "matched_token_number" : 11 + }, + "00138_00001-00160_00001" : { + "minimal_similarity" : 0.1527777777777778, + "maximum_similarity" : 0.16176470588235295, + "matched_token_number" : 22 + }, + "00013_00002-00178_00002" : { + "minimal_similarity" : 0.18452380952380953, + "maximum_similarity" : 0.23308270676691728, + "matched_token_number" : 31 + }, + "00195_00002-00203_00002" : { + "minimal_similarity" : 0.1437908496732026, + "maximum_similarity" : 0.15172413793103448, + "matched_token_number" : 22 + }, + "00137_00002-00186_00004" : { + "minimal_similarity" : 0.16666666666666666, + "maximum_similarity" : 0.19444444444444445, + "matched_token_number" : 28 + }, + "00137_00002-00186_00002" : { + "minimal_similarity" : 0.1534090909090909, + "maximum_similarity" : 0.16071428571428573, + "matched_token_number" : 27 + }, + "00095_00003-00097_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00014_00001-00155_00001" : { + "minimal_similarity" : 0.3933333333333333, + "maximum_similarity" : 0.472, + "matched_token_number" : 59 + }, + "00095_00003-00135_00001" : { + "minimal_similarity" : 0.04950495049504951, + "maximum_similarity" : 0.05434782608695652, + "matched_token_number" : 10 + }, + "00014_00001-00178_00002" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00184_00003-00197_00001" : { + "minimal_similarity" : 0.10606060606060606, + "maximum_similarity" : 0.14893617021276595, + "matched_token_number" : 14 + }, + "00000_00005-00014_00001" : { + "minimal_similarity" : 0.07333333333333333, + "maximum_similarity" : 0.0738255033557047, + "matched_token_number" : 11 + }, + "00126_00002-00160_00001" : { + "minimal_similarity" : 0.06206896551724138, + "maximum_similarity" : 0.0661764705882353, + "matched_token_number" : 9 + }, + "00134_00001-00177_00003" : { + "minimal_similarity" : 0.1488095238095238, + "maximum_similarity" : 0.21367521367521367, + "matched_token_number" : 25 + }, + "00000_00003-00014_00001" : { + "minimal_similarity" : 0.13333333333333333, + "maximum_similarity" : 0.13513513513513514, + "matched_token_number" : 20 + }, + "00156_00002-00178_00002" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00131_00005-00198_00001" : { + "minimal_similarity" : 0.050505050505050504, + "maximum_similarity" : 0.05291005291005291, + "matched_token_number" : 10 + }, + "00127_00002-00160_00001" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.16176470588235295, + "matched_token_number" : 22 + }, + "00140_00001-00198_00001" : { + "minimal_similarity" : 0.045454545454545456, + "maximum_similarity" : 0.06766917293233082, + "matched_token_number" : 9 + }, + "00113_00002-00153_00001" : { + "minimal_similarity" : 0.9940476190476191, + "maximum_similarity" : 1.0, + "matched_token_number" : 167 + }, + "00044_00002-00142_00001" : { + "minimal_similarity" : 0.10457516339869281, + "maximum_similarity" : 0.11764705882352941, + "matched_token_number" : 16 + }, + "00133_00001-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00097_00002-00135_00001" : { + "minimal_similarity" : 0.06521739130434782, + "maximum_similarity" : 0.08108108108108109, + "matched_token_number" : 12 + }, + "00136_00002-00154_00002" : { + "minimal_similarity" : 0.091324200913242, + "maximum_similarity" : 0.12195121951219512, + "matched_token_number" : 20 + }, + "00031_00003-00155_00001" : { + "minimal_similarity" : 0.2, + "maximum_similarity" : 0.21929824561403508, + "matched_token_number" : 25 + }, + "00140_00001-00204_00001" : { + "minimal_similarity" : 0.09774436090225563, + "maximum_similarity" : 0.10833333333333334, + "matched_token_number" : 13 + }, + "00127_00002-00134_00001" : { + "minimal_similarity" : 0.1488095238095238, + "maximum_similarity" : 0.21367521367521367, + "matched_token_number" : 25 + }, + "00127_00002-00186_00002" : { + "minimal_similarity" : 0.1534090909090909, + "maximum_similarity" : 0.16071428571428573, + "matched_token_number" : 27 + }, + "00125_00001-00155_00001" : { + "minimal_similarity" : 0.30357142857142855, + "maximum_similarity" : 0.408, + "matched_token_number" : 51 + }, + "00005_00002-00202_00003" : { + "minimal_similarity" : 0.1693121693121693, + "maximum_similarity" : 0.22695035460992907, + "matched_token_number" : 32 + }, + "00005_00002-00202_00002" : { + "minimal_similarity" : 0.21693121693121692, + "maximum_similarity" : 0.2907801418439716, + "matched_token_number" : 41 + }, + "00126_00002-00147_00001" : { + "minimal_similarity" : 0.12413793103448276, + "maximum_similarity" : 0.125, + "matched_token_number" : 18 + }, + "00135_00001-00160_00001" : { + "minimal_similarity" : 0.18478260869565216, + "maximum_similarity" : 0.25, + "matched_token_number" : 34 + }, + "00014_00001-00125_00001" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00133_00001-00202_00003" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00133_00001-00202_00002" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00140_00001-00145_00001" : { + "minimal_similarity" : 0.3630952380952381, + "maximum_similarity" : 0.45864661654135336, + "matched_token_number" : 61 + }, + "00097_00002-00111_00001" : { + "minimal_similarity" : 0.07738095238095238, + "maximum_similarity" : 0.08783783783783784, + "matched_token_number" : 13 + }, + "00154_00002-00192_00002" : { + "minimal_similarity" : 0.15853658536585366, + "maximum_similarity" : 0.1984732824427481, + "matched_token_number" : 26 + }, + "00097_00002-00186_00004" : { + "minimal_similarity" : 0.13513513513513514, + "maximum_similarity" : 0.1388888888888889, + "matched_token_number" : 20 + }, + "00154_00002-00192_00001" : { + "minimal_similarity" : 0.1402439024390244, + "maximum_similarity" : 0.14838709677419354, + "matched_token_number" : 23 + }, + "00137_00002-00156_00002" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00137_00002-00156_00003" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00097_00002-00186_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00003-00204_00001" : { + "minimal_similarity" : 0.060810810810810814, + "maximum_similarity" : 0.075, + "matched_token_number" : 9 + }, + "00113_00002-00155_00001" : { + "minimal_similarity" : 0.30538922155688625, + "maximum_similarity" : 0.408, + "matched_token_number" : 51 + }, + "00000_00001-00204_00001" : { + "minimal_similarity" : 0.10236220472440945, + "maximum_similarity" : 0.10833333333333334, + "matched_token_number" : 13 + }, + "00155_00001-00184_00003" : { + "minimal_similarity" : 0.224, + "maximum_similarity" : 0.2978723404255319, + "matched_token_number" : 28 + }, + "00095_00003-00156_00003" : { + "minimal_similarity" : 0.04455445544554455, + "maximum_similarity" : 0.05056179775280899, + "matched_token_number" : 9 + }, + "00155_00001-00184_00002" : { + "minimal_similarity" : 0.224, + "maximum_similarity" : 0.2978723404255319, + "matched_token_number" : 28 + }, + "00095_00003-00156_00002" : { + "minimal_similarity" : 0.04455445544554455, + "maximum_similarity" : 0.05056179775280899, + "matched_token_number" : 9 + }, + "00121_00001-00135_00001" : { + "minimal_similarity" : 0.20725388601036268, + "maximum_similarity" : 0.21739130434782608, + "matched_token_number" : 40 + }, + "00130_00002-00199_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00134_00001-00145_00001" : { + "minimal_similarity" : 0.1488095238095238, + "maximum_similarity" : 0.21367521367521367, + "matched_token_number" : 25 + }, + "00156_00002-00199_00001" : { + "minimal_similarity" : 0.06741573033707865, + "maximum_similarity" : 0.12631578947368421, + "matched_token_number" : 12 + }, + "00134_00001-00198_00001" : { + "minimal_similarity" : 0.045454545454545456, + "maximum_similarity" : 0.07692307692307693, + "matched_token_number" : 9 + }, + "00005_00002-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00135_00001-00192_00001" : { + "minimal_similarity" : 0.04891304347826087, + "maximum_similarity" : 0.05806451612903226, + "matched_token_number" : 9 + }, + "00134_00001-00203_00002" : { + "minimal_similarity" : 0.07586206896551724, + "maximum_similarity" : 0.09401709401709402, + "matched_token_number" : 11 + }, + "00135_00001-00192_00002" : { + "minimal_similarity" : 0.04891304347826087, + "maximum_similarity" : 0.06870229007633588, + "matched_token_number" : 9 + }, + "00153_00001-00187_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.17424242424242425, + "matched_token_number" : 23 + }, + "00140_00001-00177_00003" : { + "minimal_similarity" : 0.3630952380952381, + "maximum_similarity" : 0.45864661654135336, + "matched_token_number" : 61 + }, + "00031_00002-00130_00002" : { + "minimal_similarity" : 0.13533834586466165, + "maximum_similarity" : 0.14516129032258066, + "matched_token_number" : 18 + }, + "00013_00002-00204_00001" : { + "minimal_similarity" : 0.06766917293233082, + "maximum_similarity" : 0.075, + "matched_token_number" : 9 + }, + "00000_00001-00000_00002" : { + "minimal_similarity" : 0.7222222222222222, + "maximum_similarity" : 0.8188976377952756, + "matched_token_number" : 104 + }, + "00000_00001-00000_00003" : { + "minimal_similarity" : 0.7094594594594594, + "maximum_similarity" : 0.8267716535433071, + "matched_token_number" : 105 + }, + "00031_00002-00183_00004" : { + "minimal_similarity" : 0.061224489795918366, + "maximum_similarity" : 0.07258064516129033, + "matched_token_number" : 9 + }, + "00000_00001-00000_00005" : { + "minimal_similarity" : 0.6308724832214765, + "maximum_similarity" : 0.7401574803149606, + "matched_token_number" : 94 + }, + "00184_00003-00204_00001" : { + "minimal_similarity" : 0.19166666666666668, + "maximum_similarity" : 0.24468085106382978, + "matched_token_number" : 23 + }, + "00000_00003-00129_00008" : { + "minimal_similarity" : 0.031914893617021274, + "maximum_similarity" : 0.060810810810810814, + "matched_token_number" : 9 + }, + "00145_00001-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00135_00001-00198_00001" : { + "minimal_similarity" : 0.09595959595959595, + "maximum_similarity" : 0.10326086956521739, + "matched_token_number" : 19 + }, + "00044_00002-00140_00001" : { + "minimal_similarity" : 0.19117647058823528, + "maximum_similarity" : 0.19548872180451127, + "matched_token_number" : 26 + }, + "00000_00002-00156_00003" : { + "minimal_similarity" : 0.05056179775280899, + "maximum_similarity" : 0.0625, + "matched_token_number" : 9 + }, + "00044_00002-00178_00002" : { + "minimal_similarity" : 0.16071428571428573, + "maximum_similarity" : 0.19852941176470587, + "matched_token_number" : 27 + }, + "00000_00002-00156_00002" : { + "minimal_similarity" : 0.05056179775280899, + "maximum_similarity" : 0.0625, + "matched_token_number" : 9 + }, + "00014_00001-00120_00001" : { + "minimal_similarity" : 0.31333333333333335, + "maximum_similarity" : 0.32413793103448274, + "matched_token_number" : 47 + }, + "00120_00001-00135_00001" : { + "minimal_similarity" : 0.04891304347826087, + "maximum_similarity" : 0.06206896551724138, + "matched_token_number" : 9 + }, + "00005_00002-00195_00002" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.13071895424836602, + "matched_token_number" : 20 + }, + "00005_00002-00195_00001" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.13071895424836602, + "matched_token_number" : 20 + }, + "00155_00001-00186_00004" : { + "minimal_similarity" : 0.2222222222222222, + "maximum_similarity" : 0.256, + "matched_token_number" : 32 + }, + "00155_00001-00186_00002" : { + "minimal_similarity" : 0.1534090909090909, + "maximum_similarity" : 0.216, + "matched_token_number" : 27 + }, + "00013_00002-00194_00001" : { + "minimal_similarity" : 0.13333333333333333, + "maximum_similarity" : 0.15037593984962405, + "matched_token_number" : 20 + }, + "00044_00002-00126_00002" : { + "minimal_similarity" : 0.1103448275862069, + "maximum_similarity" : 0.11764705882352941, + "matched_token_number" : 16 + }, + "00156_00002-00204_00001" : { + "minimal_similarity" : 0.05056179775280899, + "maximum_similarity" : 0.075, + "matched_token_number" : 9 + }, + "00000_00003-00202_00002" : { + "minimal_similarity" : 0.1554054054054054, + "maximum_similarity" : 0.16312056737588654, + "matched_token_number" : 23 + }, + "00177_00003-00195_00002" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00000_00003-00202_00003" : { + "minimal_similarity" : 0.13513513513513514, + "maximum_similarity" : 0.14184397163120568, + "matched_token_number" : 20 + }, + "00177_00003-00195_00001" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00131_00005-00160_00001" : { + "minimal_similarity" : 0.0582010582010582, + "maximum_similarity" : 0.08088235294117647, + "matched_token_number" : 11 + }, + "00097_00002-00119_00001" : { + "minimal_similarity" : 0.18666666666666668, + "maximum_similarity" : 0.1891891891891892, + "matched_token_number" : 28 + }, + "00156_00003-00186_00004" : { + "minimal_similarity" : 0.1404494382022472, + "maximum_similarity" : 0.1736111111111111, + "matched_token_number" : 25 + }, + "00077_00001-00184_00002" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.20212765957446807, + "matched_token_number" : 19 + }, + "00156_00003-00186_00002" : { + "minimal_similarity" : 0.10112359550561797, + "maximum_similarity" : 0.10227272727272728, + "matched_token_number" : 18 + }, + "00095_00003-00186_00004" : { + "minimal_similarity" : 0.0594059405940594, + "maximum_similarity" : 0.08333333333333333, + "matched_token_number" : 12 + }, + "00095_00003-00186_00002" : { + "minimal_similarity" : 0.12871287128712872, + "maximum_similarity" : 0.14772727272727273, + "matched_token_number" : 26 + }, + "00077_00001-00184_00003" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.20212765957446807, + "matched_token_number" : 19 + }, + "00130_00002-00194_00001" : { + "minimal_similarity" : 0.32666666666666666, + "maximum_similarity" : 0.3684210526315789, + "matched_token_number" : 49 + }, + "00136_00002-00138_00001" : { + "minimal_similarity" : 0.1004566210045662, + "maximum_similarity" : 0.1527777777777778, + "matched_token_number" : 22 + }, + "00013_00002-00193_00001" : { + "minimal_similarity" : 0.16363636363636364, + "maximum_similarity" : 0.20300751879699247, + "matched_token_number" : 27 + }, + "00130_00002-00141_00002" : { + "minimal_similarity" : 0.32666666666666666, + "maximum_similarity" : 0.3684210526315789, + "matched_token_number" : 49 + }, + "00136_00002-00184_00003" : { + "minimal_similarity" : 0.0867579908675799, + "maximum_similarity" : 0.20212765957446807, + "matched_token_number" : 19 + }, + "00136_00002-00184_00002" : { + "minimal_similarity" : 0.0867579908675799, + "maximum_similarity" : 0.20212765957446807, + "matched_token_number" : 19 + }, + "00140_00001-00201_00001" : { + "minimal_similarity" : 0.06766917293233082, + "maximum_similarity" : 0.06923076923076923, + "matched_token_number" : 9 + }, + "00142_00001-00202_00003" : { + "minimal_similarity" : 0.06535947712418301, + "maximum_similarity" : 0.07092198581560284, + "matched_token_number" : 10 + }, + "00142_00001-00202_00002" : { + "minimal_similarity" : 0.06535947712418301, + "maximum_similarity" : 0.07092198581560284, + "matched_token_number" : 10 + }, + "00013_00002-00140_00001" : { + "minimal_similarity" : 0.08270676691729323, + "maximum_similarity" : 0.08270676691729323, + "matched_token_number" : 11 + }, + "00119_00001-00127_00002" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00005_00002-00031_00003" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.17543859649122806, + "matched_token_number" : 20 + }, + "00000_00001-00005_00002" : { + "minimal_similarity" : 0.06878306878306878, + "maximum_similarity" : 0.10236220472440945, + "matched_token_number" : 13 + }, + "00005_00002-00031_00002" : { + "minimal_similarity" : 0.047619047619047616, + "maximum_similarity" : 0.07258064516129033, + "matched_token_number" : 9 + }, + "00135_00001-00193_00001" : { + "minimal_similarity" : 0.08152173913043478, + "maximum_similarity" : 0.09090909090909091, + "matched_token_number" : 15 + }, + "00184_00003-00194_00001" : { + "minimal_similarity" : 0.18, + "maximum_similarity" : 0.2872340425531915, + "matched_token_number" : 27 + }, + "00177_00003-00194_00001" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00031_00002-00135_00001" : { + "minimal_similarity" : 0.10869565217391304, + "maximum_similarity" : 0.16129032258064516, + "matched_token_number" : 20 + }, + "00095_00003-00153_00001" : { + "minimal_similarity" : 0.11386138613861387, + "maximum_similarity" : 0.13690476190476192, + "matched_token_number" : 23 + }, + "00077_00001-00138_00001" : { + "minimal_similarity" : 0.09523809523809523, + "maximum_similarity" : 0.125, + "matched_token_number" : 18 + }, + "00120_00001-00130_00002" : { + "minimal_similarity" : 0.18620689655172415, + "maximum_similarity" : 0.20300751879699247, + "matched_token_number" : 27 + }, + "00133_00001-00140_00001" : { + "minimal_similarity" : 0.3630952380952381, + "maximum_similarity" : 0.45864661654135336, + "matched_token_number" : 61 + }, + "00077_00001-00131_00005" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 189 + }, + "00092_00001-00155_00001" : { + "minimal_similarity" : 0.10416666666666667, + "maximum_similarity" : 0.12, + "matched_token_number" : 15 + }, + "00013_00002-00199_00001" : { + "minimal_similarity" : 0.09774436090225563, + "maximum_similarity" : 0.1368421052631579, + "matched_token_number" : 13 + }, + "00121_00001-00134_00001" : { + "minimal_similarity" : 0.11398963730569948, + "maximum_similarity" : 0.18803418803418803, + "matched_token_number" : 22 + }, + "00044_00002-00121_00001" : { + "minimal_similarity" : 0.17098445595854922, + "maximum_similarity" : 0.2426470588235294, + "matched_token_number" : 33 + }, + "00177_00003-00200_00002" : { + "minimal_similarity" : 0.06470588235294118, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00129_00008-00154_00002" : { + "minimal_similarity" : 0.10638297872340426, + "maximum_similarity" : 0.18292682926829268, + "matched_token_number" : 30 + }, + "00013_00002-00147_00001" : { + "minimal_similarity" : 0.06944444444444445, + "maximum_similarity" : 0.07518796992481203, + "matched_token_number" : 10 + }, + "00000_00002-00137_00002" : { + "minimal_similarity" : 0.11904761904761904, + "maximum_similarity" : 0.1388888888888889, + "matched_token_number" : 20 + }, + "00136_00002-00186_00004" : { + "minimal_similarity" : 0.1461187214611872, + "maximum_similarity" : 0.2222222222222222, + "matched_token_number" : 32 + }, + "00044_00002-00177_00003" : { + "minimal_similarity" : 0.16071428571428573, + "maximum_similarity" : 0.19852941176470587, + "matched_token_number" : 27 + }, + "00142_00001-00195_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 153 + }, + "00136_00002-00186_00002" : { + "minimal_similarity" : 0.1917808219178082, + "maximum_similarity" : 0.23863636363636365, + "matched_token_number" : 42 + }, + "00142_00001-00195_00002" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 153 + }, + "00120_00001-00184_00002" : { + "minimal_similarity" : 0.11724137931034483, + "maximum_similarity" : 0.18085106382978725, + "matched_token_number" : 17 + }, + "00013_00002-00145_00001" : { + "minimal_similarity" : 0.18452380952380953, + "maximum_similarity" : 0.23308270676691728, + "matched_token_number" : 31 + }, + "00120_00001-00184_00003" : { + "minimal_similarity" : 0.11724137931034483, + "maximum_similarity" : 0.18085106382978725, + "matched_token_number" : 17 + }, + "00160_00001-00184_00003" : { + "minimal_similarity" : 0.0661764705882353, + "maximum_similarity" : 0.09574468085106383, + "matched_token_number" : 9 + }, + "00160_00001-00184_00002" : { + "minimal_similarity" : 0.0661764705882353, + "maximum_similarity" : 0.09574468085106383, + "matched_token_number" : 9 + }, + "00137_00002-00153_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00013_00002-00198_00001" : { + "minimal_similarity" : 0.14646464646464646, + "maximum_similarity" : 0.21804511278195488, + "matched_token_number" : 29 + }, + "00186_00004-00187_00001" : { + "minimal_similarity" : 0.3333333333333333, + "maximum_similarity" : 0.36363636363636365, + "matched_token_number" : 48 + }, + "00044_00002-00127_00002" : { + "minimal_similarity" : 0.16071428571428573, + "maximum_similarity" : 0.19852941176470587, + "matched_token_number" : 27 + }, + "00000_00003-00178_00002" : { + "minimal_similarity" : 0.11904761904761904, + "maximum_similarity" : 0.13513513513513514, + "matched_token_number" : 20 + }, + "00005_00002-00141_00002" : { + "minimal_similarity" : 0.1111111111111111, + "maximum_similarity" : 0.14, + "matched_token_number" : 21 + }, + "00111_00001-00113_00002" : { + "minimal_similarity" : 0.9940476190476191, + "maximum_similarity" : 1.0, + "matched_token_number" : 167 + }, + "00000_00002-00138_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00160_00001-00187_00001" : { + "minimal_similarity" : 0.0661764705882353, + "maximum_similarity" : 0.06818181818181818, + "matched_token_number" : 9 + }, + "00200_00002-00203_00002" : { + "minimal_similarity" : 0.07058823529411765, + "maximum_similarity" : 0.08275862068965517, + "matched_token_number" : 12 + }, + "00092_00001-00153_00001" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00142_00001-00203_00002" : { + "minimal_similarity" : 0.1437908496732026, + "maximum_similarity" : 0.15172413793103448, + "matched_token_number" : 22 + }, + "00077_00001-00133_00001" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00130_00002-00195_00002" : { + "minimal_similarity" : 0.17647058823529413, + "maximum_similarity" : 0.20300751879699247, + "matched_token_number" : 27 + }, + "00130_00002-00195_00001" : { + "minimal_similarity" : 0.17647058823529413, + "maximum_similarity" : 0.20300751879699247, + "matched_token_number" : 27 + }, + "00031_00002-00184_00002" : { + "minimal_similarity" : 0.0967741935483871, + "maximum_similarity" : 0.1276595744680851, + "matched_token_number" : 12 + }, + "00077_00001-00136_00002" : { + "minimal_similarity" : 0.1050228310502283, + "maximum_similarity" : 0.12169312169312169, + "matched_token_number" : 23 + }, + "00031_00002-00184_00003" : { + "minimal_similarity" : 0.0967741935483871, + "maximum_similarity" : 0.1276595744680851, + "matched_token_number" : 12 + }, + "00147_00001-00187_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00184_00003-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00003-00192_00002" : { + "minimal_similarity" : 0.19594594594594594, + "maximum_similarity" : 0.22137404580152673, + "matched_token_number" : 29 + }, + "00140_00001-00178_00002" : { + "minimal_similarity" : 0.3630952380952381, + "maximum_similarity" : 0.45864661654135336, + "matched_token_number" : 61 + }, + "00000_00003-00192_00001" : { + "minimal_similarity" : 0.1870967741935484, + "maximum_similarity" : 0.19594594594594594, + "matched_token_number" : 29 + }, + "00000_00005-00155_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00013_00002-00142_00001" : { + "minimal_similarity" : 0.06535947712418301, + "maximum_similarity" : 0.07518796992481203, + "matched_token_number" : 10 + }, + "00135_00001-00197_00001" : { + "minimal_similarity" : 0.04891304347826087, + "maximum_similarity" : 0.06818181818181818, + "matched_token_number" : 9 + }, + "00134_00001-00193_00001" : { + "minimal_similarity" : 0.07272727272727272, + "maximum_similarity" : 0.10256410256410256, + "matched_token_number" : 12 + }, + "00120_00001-00186_00004" : { + "minimal_similarity" : 0.1103448275862069, + "maximum_similarity" : 0.1111111111111111, + "matched_token_number" : 16 + }, + "00000_00003-00127_00002" : { + "minimal_similarity" : 0.11904761904761904, + "maximum_similarity" : 0.13513513513513514, + "matched_token_number" : 20 + }, + "00142_00001-00197_00001" : { + "minimal_similarity" : 0.08496732026143791, + "maximum_similarity" : 0.09848484848484848, + "matched_token_number" : 13 + }, + "00120_00001-00186_00002" : { + "minimal_similarity" : 0.09090909090909091, + "maximum_similarity" : 0.1103448275862069, + "matched_token_number" : 16 + }, + "00000_00003-00140_00001" : { + "minimal_similarity" : 0.060810810810810814, + "maximum_similarity" : 0.06766917293233082, + "matched_token_number" : 9 + }, + "00134_00001-00140_00001" : { + "minimal_similarity" : 0.37593984962406013, + "maximum_similarity" : 0.42735042735042733, + "matched_token_number" : 50 + }, + "00156_00002-00194_00001" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.07333333333333333, + "matched_token_number" : 11 + }, + "00005_00002-00127_00002" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00077_00001-00135_00001" : { + "minimal_similarity" : 0.09523809523809523, + "maximum_similarity" : 0.09782608695652174, + "matched_token_number" : 18 + }, + "00130_00002-00202_00002" : { + "minimal_similarity" : 0.07092198581560284, + "maximum_similarity" : 0.07518796992481203, + "matched_token_number" : 10 + }, + "00135_00001-00203_00002" : { + "minimal_similarity" : 0.059782608695652176, + "maximum_similarity" : 0.07586206896551724, + "matched_token_number" : 11 + }, + "00136_00002-00187_00001" : { + "minimal_similarity" : 0.045662100456621, + "maximum_similarity" : 0.07575757575757576, + "matched_token_number" : 10 + }, + "00130_00002-00197_00001" : { + "minimal_similarity" : 0.09774436090225563, + "maximum_similarity" : 0.09848484848484848, + "matched_token_number" : 13 + }, + "00013_00002-00196_00001" : { + "minimal_similarity" : 0.027548209366391185, + "maximum_similarity" : 0.07518796992481203, + "matched_token_number" : 10 + }, + "00130_00002-00202_00003" : { + "minimal_similarity" : 0.07092198581560284, + "maximum_similarity" : 0.07518796992481203, + "matched_token_number" : 10 + }, + "00156_00002-00193_00001" : { + "minimal_similarity" : 0.06741573033707865, + "maximum_similarity" : 0.07272727272727272, + "matched_token_number" : 12 + }, + "00113_00002-00120_00001" : { + "minimal_similarity" : 0.2155688622754491, + "maximum_similarity" : 0.2482758620689655, + "matched_token_number" : 36 + }, + "00184_00003-00192_00002" : { + "minimal_similarity" : 0.16030534351145037, + "maximum_similarity" : 0.22340425531914893, + "matched_token_number" : 21 + }, + "00184_00003-00192_00001" : { + "minimal_similarity" : 0.09032258064516129, + "maximum_similarity" : 0.14893617021276595, + "matched_token_number" : 14 + }, + "00133_00001-00178_00002" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00120_00001-00133_00001" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.2482758620689655, + "matched_token_number" : 36 + }, + "00000_00002-00092_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00121_00001-00137_00002" : { + "minimal_similarity" : 0.7046632124352331, + "maximum_similarity" : 0.8095238095238095, + "matched_token_number" : 136 + }, + "00153_00001-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00203_00002-00204_00001" : { + "minimal_similarity" : 0.2, + "maximum_similarity" : 0.24166666666666667, + "matched_token_number" : 29 + }, + "00121_00001-00198_00001" : { + "minimal_similarity" : 0.20202020202020202, + "maximum_similarity" : 0.20725388601036268, + "matched_token_number" : 40 + }, + "00140_00001-00194_00001" : { + "minimal_similarity" : 0.32666666666666666, + "maximum_similarity" : 0.3684210526315789, + "matched_token_number" : 49 + }, + "00077_00001-00127_00002" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00184_00003-00196_00001" : { + "minimal_similarity" : 0.024793388429752067, + "maximum_similarity" : 0.09574468085106383, + "matched_token_number" : 9 + }, + "00135_00001-00142_00001" : { + "minimal_similarity" : 0.04891304347826087, + "maximum_similarity" : 0.058823529411764705, + "matched_token_number" : 9 + }, + "00000_00005-00141_00002" : { + "minimal_similarity" : 0.07333333333333333, + "maximum_similarity" : 0.0738255033557047, + "matched_token_number" : 11 + }, + "00031_00002-00120_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00031_00003-00095_00003" : { + "minimal_similarity" : 0.0594059405940594, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 12 + }, + "00031_00002-00095_00003" : { + "minimal_similarity" : 0.04455445544554455, + "maximum_similarity" : 0.07258064516129033, + "matched_token_number" : 9 + }, + "00044_00002-00130_00002" : { + "minimal_similarity" : 0.19117647058823528, + "maximum_similarity" : 0.19548872180451127, + "matched_token_number" : 26 + }, + "00136_00002-00195_00002" : { + "minimal_similarity" : 0.0547945205479452, + "maximum_similarity" : 0.0784313725490196, + "matched_token_number" : 12 + }, + "00113_00002-00119_00001" : { + "minimal_similarity" : 0.2634730538922156, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00136_00002-00195_00001" : { + "minimal_similarity" : 0.0547945205479452, + "maximum_similarity" : 0.0784313725490196, + "matched_token_number" : 12 + }, + "00126_00002-00129_00008" : { + "minimal_similarity" : 0.0425531914893617, + "maximum_similarity" : 0.08275862068965517, + "matched_token_number" : 12 + }, + "00000_00002-00141_00002" : { + "minimal_similarity" : 0.13333333333333333, + "maximum_similarity" : 0.1388888888888889, + "matched_token_number" : 20 + }, + "00201_00001-00204_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00178_00002-00184_00003" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.2765957446808511, + "matched_token_number" : 26 + }, + "00178_00002-00184_00002" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.2765957446808511, + "matched_token_number" : 26 + }, + "00111_00001-00127_00002" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00137_00002-00155_00001" : { + "minimal_similarity" : 0.30357142857142855, + "maximum_similarity" : 0.408, + "matched_token_number" : 51 + }, + "00014_00001-00129_00008" : { + "minimal_similarity" : 0.10638297872340426, + "maximum_similarity" : 0.2, + "matched_token_number" : 30 + }, + "00142_00001-00199_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00095_00003-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00113_00002-00186_00004" : { + "minimal_similarity" : 0.16766467065868262, + "maximum_similarity" : 0.19444444444444445, + "matched_token_number" : 28 + }, + "00140_00001-00199_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00177_00003-00178_00002" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00000_00001-00095_00003" : { + "minimal_similarity" : 0.11386138613861387, + "maximum_similarity" : 0.18110236220472442, + "matched_token_number" : 23 + }, + "00138_00001-00204_00001" : { + "minimal_similarity" : 0.06944444444444445, + "maximum_similarity" : 0.08333333333333333, + "matched_token_number" : 10 + }, + "00126_00002-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00097_00002-00155_00001" : { + "minimal_similarity" : 0.4189189189189189, + "maximum_similarity" : 0.496, + "matched_token_number" : 62 + }, + "00000_00001-00120_00001" : { + "minimal_similarity" : 0.1724137931034483, + "maximum_similarity" : 0.1968503937007874, + "matched_token_number" : 25 + }, + "00113_00002-00186_00002" : { + "minimal_similarity" : 0.1534090909090909, + "maximum_similarity" : 0.16167664670658682, + "matched_token_number" : 27 + }, + "00031_00002-00192_00002" : { + "minimal_similarity" : 0.09923664122137404, + "maximum_similarity" : 0.10483870967741936, + "matched_token_number" : 13 + }, + "00160_00001-00201_00001" : { + "minimal_similarity" : 0.0661764705882353, + "maximum_similarity" : 0.06923076923076923, + "matched_token_number" : 9 + }, + "00031_00002-00192_00001" : { + "minimal_similarity" : 0.1032258064516129, + "maximum_similarity" : 0.12903225806451613, + "matched_token_number" : 16 + }, + "00077_00001-00097_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00131_00005-00184_00002" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.20212765957446807, + "matched_token_number" : 19 + }, + "00131_00005-00184_00003" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.20212765957446807, + "matched_token_number" : 19 + }, + "00192_00001-00195_00002" : { + "minimal_similarity" : 0.08387096774193549, + "maximum_similarity" : 0.08496732026143791, + "matched_token_number" : 13 + }, + "00192_00001-00195_00001" : { + "minimal_similarity" : 0.08387096774193549, + "maximum_similarity" : 0.08496732026143791, + "matched_token_number" : 13 + }, + "00142_00001-00160_00001" : { + "minimal_similarity" : 0.058823529411764705, + "maximum_similarity" : 0.0661764705882353, + "matched_token_number" : 9 + }, + "00000_00005-00154_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00129_00008-00130_00002" : { + "minimal_similarity" : 0.07801418439716312, + "maximum_similarity" : 0.16541353383458646, + "matched_token_number" : 22 + }, + "00131_00005-00197_00001" : { + "minimal_similarity" : 0.05291005291005291, + "maximum_similarity" : 0.07575757575757576, + "matched_token_number" : 10 + }, + "00005_00002-00119_00001" : { + "minimal_similarity" : 0.1111111111111111, + "maximum_similarity" : 0.14, + "matched_token_number" : 21 + }, + "00186_00004-00196_00001" : { + "minimal_similarity" : 0.030303030303030304, + "maximum_similarity" : 0.0763888888888889, + "matched_token_number" : 11 + }, + "00000_00001-00154_00002" : { + "minimal_similarity" : 0.0975609756097561, + "maximum_similarity" : 0.12598425196850394, + "matched_token_number" : 16 + }, + "00000_00003-00044_00002" : { + "minimal_similarity" : 0.2702702702702703, + "maximum_similarity" : 0.29411764705882354, + "matched_token_number" : 40 + }, + "00119_00001-00160_00001" : { + "minimal_similarity" : 0.08, + "maximum_similarity" : 0.08823529411764706, + "matched_token_number" : 12 + }, + "00119_00001-00131_00005" : { + "minimal_similarity" : 0.1111111111111111, + "maximum_similarity" : 0.14, + "matched_token_number" : 21 + }, + "00120_00001-00153_00001" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.2482758620689655, + "matched_token_number" : 36 + }, + "00092_00001-00131_00005" : { + "minimal_similarity" : 0.09523809523809523, + "maximum_similarity" : 0.125, + "matched_token_number" : 18 + }, + "00000_00002-00044_00002" : { + "minimal_similarity" : 0.2777777777777778, + "maximum_similarity" : 0.29411764705882354, + "matched_token_number" : 40 + }, + "00134_00001-00195_00002" : { + "minimal_similarity" : 0.16339869281045752, + "maximum_similarity" : 0.21367521367521367, + "matched_token_number" : 25 + }, + "00014_00001-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00134_00001-00195_00001" : { + "minimal_similarity" : 0.16339869281045752, + "maximum_similarity" : 0.21367521367521367, + "matched_token_number" : 25 + }, + "00077_00001-00194_00001" : { + "minimal_similarity" : 0.1111111111111111, + "maximum_similarity" : 0.14, + "matched_token_number" : 21 + }, + "00000_00005-00095_00003" : { + "minimal_similarity" : 0.09900990099009901, + "maximum_similarity" : 0.1342281879194631, + "matched_token_number" : 20 + }, + "00194_00001-00195_00001" : { + "minimal_similarity" : 0.30718954248366015, + "maximum_similarity" : 0.31333333333333335, + "matched_token_number" : 47 + }, + "00194_00001-00195_00002" : { + "minimal_similarity" : 0.30718954248366015, + "maximum_similarity" : 0.31333333333333335, + "matched_token_number" : 47 + }, + "00000_00005-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00137_00002-00193_00001" : { + "minimal_similarity" : 0.07142857142857142, + "maximum_similarity" : 0.07272727272727272, + "matched_token_number" : 12 + }, + "00000_00002-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00001-00125_00001" : { + "minimal_similarity" : 0.1488095238095238, + "maximum_similarity" : 0.1968503937007874, + "matched_token_number" : 25 + }, + "00077_00001-00092_00001" : { + "minimal_similarity" : 0.09523809523809523, + "maximum_similarity" : 0.125, + "matched_token_number" : 18 + }, + "00014_00001-00044_00002" : { + "minimal_similarity" : 0.18, + "maximum_similarity" : 0.19852941176470587, + "matched_token_number" : 27 + }, + "00111_00001-00160_00001" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.16176470588235295, + "matched_token_number" : 22 + }, + "00031_00002-00197_00001" : { + "minimal_similarity" : 0.13636363636363635, + "maximum_similarity" : 0.14516129032258066, + "matched_token_number" : 18 + }, + "00119_00001-00194_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 150 + }, + "00133_00001-00197_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.17424242424242425, + "matched_token_number" : 23 + }, + "00177_00003-00199_00001" : { + "minimal_similarity" : 0.05952380952380952, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 10 + }, + "00000_00003-00138_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00187_00001-00194_00001" : { + "minimal_similarity" : 0.08666666666666667, + "maximum_similarity" : 0.09848484848484848, + "matched_token_number" : 13 + }, + "00142_00001-00178_00002" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00111_00001-00156_00002" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00077_00001-00130_00002" : { + "minimal_similarity" : 0.06349206349206349, + "maximum_similarity" : 0.09022556390977443, + "matched_token_number" : 12 + }, + "00111_00001-00156_00003" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00125_00001-00130_00002" : { + "minimal_similarity" : 0.3630952380952381, + "maximum_similarity" : 0.45864661654135336, + "matched_token_number" : 61 + }, + "00111_00001-00199_00001" : { + "minimal_similarity" : 0.05952380952380952, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 10 + }, + "00141_00002-00192_00001" : { + "minimal_similarity" : 0.08387096774193549, + "maximum_similarity" : 0.08666666666666667, + "matched_token_number" : 13 + }, + "00141_00002-00192_00002" : { + "minimal_similarity" : 0.11333333333333333, + "maximum_similarity" : 0.1297709923664122, + "matched_token_number" : 17 + }, + "00156_00002-00198_00001" : { + "minimal_similarity" : 0.09090909090909091, + "maximum_similarity" : 0.10112359550561797, + "matched_token_number" : 18 + }, + "00153_00001-00200_00002" : { + "minimal_similarity" : 0.06470588235294118, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00131_00005-00155_00001" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.152, + "matched_token_number" : 19 + }, + "00077_00001-00199_00001" : { + "minimal_similarity" : 0.047619047619047616, + "maximum_similarity" : 0.09473684210526316, + "matched_token_number" : 9 + }, + "00184_00002-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00097_00002-00192_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00097_00002-00192_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00119_00001-00136_00002" : { + "minimal_similarity" : 0.1004566210045662, + "maximum_similarity" : 0.14666666666666667, + "matched_token_number" : 22 + }, + "00126_00002-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00097_00002-00184_00003" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00097_00002-00184_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00031_00003-00184_00002" : { + "minimal_similarity" : 0.23684210526315788, + "maximum_similarity" : 0.2872340425531915, + "matched_token_number" : 27 + }, + "00044_00002-00194_00001" : { + "minimal_similarity" : 0.18, + "maximum_similarity" : 0.19852941176470587, + "matched_token_number" : 27 + }, + "00031_00003-00184_00003" : { + "minimal_similarity" : 0.23684210526315788, + "maximum_similarity" : 0.2872340425531915, + "matched_token_number" : 27 + }, + "00031_00002-00031_00003" : { + "minimal_similarity" : 0.1935483870967742, + "maximum_similarity" : 0.21052631578947367, + "matched_token_number" : 24 + }, + "00013_00002-00127_00002" : { + "minimal_similarity" : 0.18452380952380953, + "maximum_similarity" : 0.23308270676691728, + "matched_token_number" : 31 + }, + "00113_00002-00156_00003" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.0658682634730539, + "matched_token_number" : 11 + }, + "00113_00002-00156_00002" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.0658682634730539, + "matched_token_number" : 11 + }, + "00125_00001-00126_00002" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.2482758620689655, + "matched_token_number" : 36 + }, + "00202_00002-00202_00003" : { + "minimal_similarity" : 0.9645390070921985, + "maximum_similarity" : 0.9645390070921985, + "matched_token_number" : 136 + }, + "00197_00001-00198_00001" : { + "minimal_similarity" : 0.14646464646464646, + "maximum_similarity" : 0.2196969696969697, + "matched_token_number" : 29 + }, + "00120_00001-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00092_00001-00136_00002" : { + "minimal_similarity" : 0.1004566210045662, + "maximum_similarity" : 0.1527777777777778, + "matched_token_number" : 22 + }, + "00095_00003-00184_00003" : { + "minimal_similarity" : 0.0594059405940594, + "maximum_similarity" : 0.1276595744680851, + "matched_token_number" : 12 + }, + "00156_00003-00194_00001" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.07333333333333333, + "matched_token_number" : 11 + }, + "00121_00001-00130_00002" : { + "minimal_similarity" : 0.23834196891191708, + "maximum_similarity" : 0.3458646616541353, + "matched_token_number" : 46 + }, + "00095_00003-00184_00002" : { + "minimal_similarity" : 0.0594059405940594, + "maximum_similarity" : 0.1276595744680851, + "matched_token_number" : 12 + }, + "00111_00001-00119_00001" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00154_00002-00193_00001" : { + "minimal_similarity" : 0.07272727272727272, + "maximum_similarity" : 0.07317073170731707, + "matched_token_number" : 12 + }, + "00000_00003-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00155_00001-00183_00004" : { + "minimal_similarity" : 0.09523809523809523, + "maximum_similarity" : 0.112, + "matched_token_number" : 14 + }, + "00000_00001-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00156_00002-00177_00003" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00129_00008-00198_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00044_00002-00135_00001" : { + "minimal_similarity" : 0.10869565217391304, + "maximum_similarity" : 0.14705882352941177, + "matched_token_number" : 20 + }, + "00121_00001-00126_00002" : { + "minimal_similarity" : 0.17098445595854922, + "maximum_similarity" : 0.22758620689655173, + "matched_token_number" : 33 + }, + "00013_00002-00156_00002" : { + "minimal_similarity" : 0.056179775280898875, + "maximum_similarity" : 0.07518796992481203, + "matched_token_number" : 10 + }, + "00013_00002-00156_00003" : { + "minimal_similarity" : 0.056179775280898875, + "maximum_similarity" : 0.07518796992481203, + "matched_token_number" : 10 + }, + "00156_00003-00193_00001" : { + "minimal_similarity" : 0.06741573033707865, + "maximum_similarity" : 0.07272727272727272, + "matched_token_number" : 12 + }, + "00127_00002-00156_00002" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00127_00002-00156_00003" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00178_00002-00201_00001" : { + "minimal_similarity" : 0.05357142857142857, + "maximum_similarity" : 0.06923076923076923, + "matched_token_number" : 9 + }, + "00125_00001-00127_00002" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00000_00001-00197_00001" : { + "minimal_similarity" : 0.25757575757575757, + "maximum_similarity" : 0.2677165354330709, + "matched_token_number" : 34 + }, + "00136_00002-00153_00001" : { + "minimal_similarity" : 0.0867579908675799, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00000_00003-00197_00001" : { + "minimal_similarity" : 0.20270270270270271, + "maximum_similarity" : 0.22727272727272727, + "matched_token_number" : 30 + }, + "00113_00002-00178_00002" : { + "minimal_similarity" : 0.9940476190476191, + "maximum_similarity" : 1.0, + "matched_token_number" : 167 + }, + "00192_00002-00204_00001" : { + "minimal_similarity" : 0.183206106870229, + "maximum_similarity" : 0.2, + "matched_token_number" : 24 + }, + "00195_00002-00202_00002" : { + "minimal_similarity" : 0.06535947712418301, + "maximum_similarity" : 0.07092198581560284, + "matched_token_number" : 10 + }, + "00195_00002-00202_00003" : { + "minimal_similarity" : 0.06535947712418301, + "maximum_similarity" : 0.07092198581560284, + "matched_token_number" : 10 + }, + "00133_00001-00138_00001" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00126_00002-00153_00001" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.2482758620689655, + "matched_token_number" : 36 + }, + "00005_00002-00203_00002" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.13793103448275862, + "matched_token_number" : 20 + }, + "00031_00003-00154_00002" : { + "minimal_similarity" : 0.14634146341463414, + "maximum_similarity" : 0.21052631578947367, + "matched_token_number" : 24 + }, + "00013_00002-00097_00002" : { + "minimal_similarity" : 0.06756756756756757, + "maximum_similarity" : 0.07518796992481203, + "matched_token_number" : 10 + }, + "00193_00001-00197_00001" : { + "minimal_similarity" : 0.11515151515151516, + "maximum_similarity" : 0.14393939393939395, + "matched_token_number" : 19 + }, + "00125_00001-00134_00001" : { + "minimal_similarity" : 0.1488095238095238, + "maximum_similarity" : 0.21367521367521367, + "matched_token_number" : 25 + }, + "00121_00001-00155_00001" : { + "minimal_similarity" : 0.3005181347150259, + "maximum_similarity" : 0.464, + "matched_token_number" : 58 + }, + "00156_00003-00199_00001" : { + "minimal_similarity" : 0.06741573033707865, + "maximum_similarity" : 0.12631578947368421, + "matched_token_number" : 12 + }, + "00187_00001-00198_00001" : { + "minimal_similarity" : 0.14646464646464646, + "maximum_similarity" : 0.2196969696969697, + "matched_token_number" : 29 + }, + "00013_00002-00119_00001" : { + "minimal_similarity" : 0.13333333333333333, + "maximum_similarity" : 0.15037593984962405, + "matched_token_number" : 20 + }, + "00000_00001-00129_00008" : { + "minimal_similarity" : 0.0425531914893617, + "maximum_similarity" : 0.09448818897637795, + "matched_token_number" : 12 + }, + "00119_00001-00135_00001" : { + "minimal_similarity" : 0.1956521739130435, + "maximum_similarity" : 0.24, + "matched_token_number" : 36 + }, + "00044_00002-00193_00001" : { + "minimal_similarity" : 0.2606060606060606, + "maximum_similarity" : 0.3161764705882353, + "matched_token_number" : 43 + }, + "00092_00001-00127_00002" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00031_00003-00183_00004" : { + "minimal_similarity" : 0.14285714285714285, + "maximum_similarity" : 0.18421052631578946, + "matched_token_number" : 21 + }, + "00154_00002-00194_00001" : { + "minimal_similarity" : 0.2682926829268293, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00126_00002-00187_00001" : { + "minimal_similarity" : 0.0896551724137931, + "maximum_similarity" : 0.09848484848484848, + "matched_token_number" : 13 + }, + "00097_00002-00193_00001" : { + "minimal_similarity" : 0.05454545454545454, + "maximum_similarity" : 0.060810810810810814, + "matched_token_number" : 9 + }, + "00129_00008-00193_00001" : { + "minimal_similarity" : 0.031914893617021274, + "maximum_similarity" : 0.05454545454545454, + "matched_token_number" : 9 + }, + "00013_00002-00126_00002" : { + "minimal_similarity" : 0.06896551724137931, + "maximum_similarity" : 0.07518796992481203, + "matched_token_number" : 10 + }, + "00044_00002-00160_00001" : { + "minimal_similarity" : 0.09558823529411764, + "maximum_similarity" : 0.09558823529411764, + "matched_token_number" : 13 + }, + "00000_00002-00184_00002" : { + "minimal_similarity" : 0.0625, + "maximum_similarity" : 0.09574468085106383, + "matched_token_number" : 9 + }, + "00031_00002-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00002-00184_00003" : { + "minimal_similarity" : 0.0625, + "maximum_similarity" : 0.09574468085106383, + "matched_token_number" : 9 + }, + "00127_00002-00199_00001" : { + "minimal_similarity" : 0.05952380952380952, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 10 + }, + "00000_00001-00184_00003" : { + "minimal_similarity" : 0.11023622047244094, + "maximum_similarity" : 0.14893617021276595, + "matched_token_number" : 14 + }, + "00000_00005-00184_00003" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00005_00002-00097_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00001-00184_00002" : { + "minimal_similarity" : 0.11023622047244094, + "maximum_similarity" : 0.14893617021276595, + "matched_token_number" : 14 + }, + "00000_00005-00184_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00127_00002-00186_00004" : { + "minimal_similarity" : 0.16666666666666666, + "maximum_similarity" : 0.19444444444444445, + "matched_token_number" : 28 + }, + "00156_00003-00160_00001" : { + "minimal_similarity" : 0.10112359550561797, + "maximum_similarity" : 0.1323529411764706, + "matched_token_number" : 18 + }, + "00145_00001-00201_00001" : { + "minimal_similarity" : 0.05357142857142857, + "maximum_similarity" : 0.06923076923076923, + "matched_token_number" : 9 + }, + "00156_00002-00160_00001" : { + "minimal_similarity" : 0.10112359550561797, + "maximum_similarity" : 0.1323529411764706, + "matched_token_number" : 18 + }, + "00183_00004-00193_00001" : { + "minimal_similarity" : 0.05454545454545454, + "maximum_similarity" : 0.061224489795918366, + "matched_token_number" : 9 + }, + "00125_00001-00194_00001" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00183_00004-00199_00001" : { + "minimal_similarity" : 0.061224489795918366, + "maximum_similarity" : 0.09473684210526316, + "matched_token_number" : 9 + }, + "00142_00001-00177_00003" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00000_00005-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00129_00008-00194_00001" : { + "minimal_similarity" : 0.10638297872340426, + "maximum_similarity" : 0.2, + "matched_token_number" : 30 + }, + "00000_00002-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00135_00001-00177_00003" : { + "minimal_similarity" : 0.1956521739130435, + "maximum_similarity" : 0.21428571428571427, + "matched_token_number" : 36 + }, + "00111_00001-00198_00001" : { + "minimal_similarity" : 0.18686868686868688, + "maximum_similarity" : 0.22023809523809523, + "matched_token_number" : 37 + }, + "00186_00002-00204_00001" : { + "minimal_similarity" : 0.13636363636363635, + "maximum_similarity" : 0.2, + "matched_token_number" : 24 + }, + "00127_00002-00193_00001" : { + "minimal_similarity" : 0.07142857142857142, + "maximum_similarity" : 0.07272727272727272, + "matched_token_number" : 12 + }, + "00014_00001-00138_00001" : { + "minimal_similarity" : 0.1, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00153_00001-00204_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.19166666666666668, + "matched_token_number" : 23 + }, + "00145_00001-00200_00002" : { + "minimal_similarity" : 0.06470588235294118, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00000_00005-00201_00001" : { + "minimal_similarity" : 0.06040268456375839, + "maximum_similarity" : 0.06923076923076923, + "matched_token_number" : 9 + }, + "00013_00002-00113_00002" : { + "minimal_similarity" : 0.18562874251497005, + "maximum_similarity" : 0.23308270676691728, + "matched_token_number" : 31 + }, + "00121_00001-00156_00003" : { + "minimal_similarity" : 0.05699481865284974, + "maximum_similarity" : 0.06179775280898876, + "matched_token_number" : 11 + }, + "00138_00001-00145_00001" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00121_00001-00156_00002" : { + "minimal_similarity" : 0.05699481865284974, + "maximum_similarity" : 0.06179775280898876, + "matched_token_number" : 11 + }, + "00125_00001-00135_00001" : { + "minimal_similarity" : 0.1956521739130435, + "maximum_similarity" : 0.21428571428571427, + "matched_token_number" : 36 + }, + "00141_00002-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00001-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00187_00001-00199_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00141_00002-00197_00001" : { + "minimal_similarity" : 0.08666666666666667, + "maximum_similarity" : 0.09848484848484848, + "matched_token_number" : 13 + }, + "00193_00001-00198_00001" : { + "minimal_similarity" : 0.09090909090909091, + "maximum_similarity" : 0.10909090909090909, + "matched_token_number" : 18 + }, + "00127_00002-00194_00001" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00014_00001-00133_00001" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00125_00001-00193_00001" : { + "minimal_similarity" : 0.07142857142857142, + "maximum_similarity" : 0.07272727272727272, + "matched_token_number" : 12 + }, + "00183_00004-00198_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00119_00001-00195_00002" : { + "minimal_similarity" : 0.30718954248366015, + "maximum_similarity" : 0.31333333333333335, + "matched_token_number" : 47 + }, + "00119_00001-00195_00001" : { + "minimal_similarity" : 0.30718954248366015, + "maximum_similarity" : 0.31333333333333335, + "matched_token_number" : 47 + }, + "00133_00001-00198_00001" : { + "minimal_similarity" : 0.18686868686868688, + "maximum_similarity" : 0.22023809523809523, + "matched_token_number" : 37 + }, + "00154_00002-00160_00001" : { + "minimal_similarity" : 0.17682926829268292, + "maximum_similarity" : 0.21323529411764705, + "matched_token_number" : 29 + }, + "00134_00001-00160_00001" : { + "minimal_similarity" : 0.16176470588235295, + "maximum_similarity" : 0.18803418803418803, + "matched_token_number" : 22 + }, + "00095_00003-00113_00002" : { + "minimal_similarity" : 0.11386138613861387, + "maximum_similarity" : 0.1377245508982036, + "matched_token_number" : 23 + }, + "00183_00004-00186_00004" : { + "minimal_similarity" : 0.2585034013605442, + "maximum_similarity" : 0.2638888888888889, + "matched_token_number" : 38 + }, + "00125_00001-00199_00001" : { + "minimal_similarity" : 0.05952380952380952, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 10 + }, + "00183_00004-00186_00002" : { + "minimal_similarity" : 0.056818181818181816, + "maximum_similarity" : 0.06802721088435375, + "matched_token_number" : 10 + }, + "00097_00002-00154_00002" : { + "minimal_similarity" : 0.07926829268292683, + "maximum_similarity" : 0.08783783783783784, + "matched_token_number" : 13 + }, + "00111_00001-00193_00001" : { + "minimal_similarity" : 0.07142857142857142, + "maximum_similarity" : 0.07272727272727272, + "matched_token_number" : 12 + }, + "00154_00002-00198_00001" : { + "minimal_similarity" : 0.14646464646464646, + "maximum_similarity" : 0.17682926829268292, + "matched_token_number" : 29 + }, + "00113_00002-00203_00002" : { + "minimal_similarity" : 0.1377245508982036, + "maximum_similarity" : 0.15862068965517243, + "matched_token_number" : 23 + }, + "00014_00001-00192_00002" : { + "minimal_similarity" : 0.11333333333333333, + "maximum_similarity" : 0.1297709923664122, + "matched_token_number" : 17 + }, + "00014_00001-00192_00001" : { + "minimal_similarity" : 0.08387096774193549, + "maximum_similarity" : 0.08666666666666667, + "matched_token_number" : 13 + }, + "00127_00002-00198_00001" : { + "minimal_similarity" : 0.18686868686868688, + "maximum_similarity" : 0.22023809523809523, + "matched_token_number" : 37 + }, + "00145_00001-00147_00001" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00178_00002-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00014_00001-00195_00001" : { + "minimal_similarity" : 0.30718954248366015, + "maximum_similarity" : 0.31333333333333335, + "matched_token_number" : 47 + }, + "00014_00001-00077_00001" : { + "minimal_similarity" : 0.1111111111111111, + "maximum_similarity" : 0.14, + "matched_token_number" : 21 + }, + "00186_00002-00187_00001" : { + "minimal_similarity" : 0.3125, + "maximum_similarity" : 0.4166666666666667, + "matched_token_number" : 55 + }, + "00138_00001-00203_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00120_00001-00154_00002" : { + "minimal_similarity" : 0.15853658536585366, + "maximum_similarity" : 0.1793103448275862, + "matched_token_number" : 26 + }, + "00111_00001-00186_00002" : { + "minimal_similarity" : 0.1534090909090909, + "maximum_similarity" : 0.16071428571428573, + "matched_token_number" : 27 + }, + "00138_00001-00140_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00014_00001-00195_00002" : { + "minimal_similarity" : 0.30718954248366015, + "maximum_similarity" : 0.31333333333333335, + "matched_token_number" : 47 + }, + "00111_00001-00186_00004" : { + "minimal_similarity" : 0.16666666666666666, + "maximum_similarity" : 0.19444444444444445, + "matched_token_number" : 28 + }, + "00077_00001-00160_00001" : { + "minimal_similarity" : 0.0582010582010582, + "maximum_similarity" : 0.08088235294117647, + "matched_token_number" : 11 + }, + "00000_00001-00031_00002" : { + "minimal_similarity" : 0.14960629921259844, + "maximum_similarity" : 0.1532258064516129, + "matched_token_number" : 19 + }, + "00192_00001-00199_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00001-00031_00003" : { + "minimal_similarity" : 0.2440944881889764, + "maximum_similarity" : 0.2719298245614035, + "matched_token_number" : 31 + }, + "00126_00002-00195_00001" : { + "minimal_similarity" : 0.9477124183006536, + "maximum_similarity" : 1.0, + "matched_token_number" : 145 + }, + "00126_00002-00195_00002" : { + "minimal_similarity" : 0.9477124183006536, + "maximum_similarity" : 1.0, + "matched_token_number" : 145 + }, + "00031_00003-00141_00002" : { + "minimal_similarity" : 0.16, + "maximum_similarity" : 0.21052631578947367, + "matched_token_number" : 24 + }, + "00125_00001-00198_00001" : { + "minimal_similarity" : 0.18686868686868688, + "maximum_similarity" : 0.22023809523809523, + "matched_token_number" : 37 + }, + "00131_00005-00192_00002" : { + "minimal_similarity" : 0.05291005291005291, + "maximum_similarity" : 0.07633587786259542, + "matched_token_number" : 10 + }, + "00077_00001-00156_00002" : { + "minimal_similarity" : 0.047619047619047616, + "maximum_similarity" : 0.05056179775280899, + "matched_token_number" : 9 + }, + "00131_00005-00192_00001" : { + "minimal_similarity" : 0.05291005291005291, + "maximum_similarity" : 0.06451612903225806, + "matched_token_number" : 10 + }, + "00077_00001-00156_00003" : { + "minimal_similarity" : 0.047619047619047616, + "maximum_similarity" : 0.05056179775280899, + "matched_token_number" : 9 + }, + "00129_00008-00135_00001" : { + "minimal_similarity" : 0.08156028368794327, + "maximum_similarity" : 0.125, + "matched_token_number" : 23 + }, + "00014_00001-00137_00002" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00119_00001-00199_00001" : { + "minimal_similarity" : 0.06666666666666667, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 10 + }, + "00156_00003-00198_00001" : { + "minimal_similarity" : 0.09090909090909091, + "maximum_similarity" : 0.10112359550561797, + "matched_token_number" : 18 + }, + "00192_00001-00196_00001" : { + "minimal_similarity" : 0.024793388429752067, + "maximum_similarity" : 0.05806451612903226, + "matched_token_number" : 9 + }, + "00000_00002-00014_00001" : { + "minimal_similarity" : 0.13333333333333333, + "maximum_similarity" : 0.1388888888888889, + "matched_token_number" : 20 + }, + "00141_00002-00155_00001" : { + "minimal_similarity" : 0.3933333333333333, + "maximum_similarity" : 0.472, + "matched_token_number" : 59 + }, + "00092_00001-00130_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00140_00001-00160_00001" : { + "minimal_similarity" : 0.16911764705882354, + "maximum_similarity" : 0.17293233082706766, + "matched_token_number" : 23 + }, + "00000_00001-00192_00001" : { + "minimal_similarity" : 0.2129032258064516, + "maximum_similarity" : 0.25984251968503935, + "matched_token_number" : 33 + }, + "00000_00001-00192_00002" : { + "minimal_similarity" : 0.2595419847328244, + "maximum_similarity" : 0.2677165354330709, + "matched_token_number" : 34 + }, + "00000_00005-00140_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00141_00002-00153_00001" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00031_00003-00142_00001" : { + "minimal_similarity" : 0.0915032679738562, + "maximum_similarity" : 0.12280701754385964, + "matched_token_number" : 14 + }, + "00126_00002-00192_00001" : { + "minimal_similarity" : 0.08387096774193549, + "maximum_similarity" : 0.0896551724137931, + "matched_token_number" : 13 + }, + "00031_00003-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00044_00002-00198_00001" : { + "minimal_similarity" : 0.08080808080808081, + "maximum_similarity" : 0.11764705882352941, + "matched_token_number" : 16 + }, + "00154_00002-00199_00001" : { + "minimal_similarity" : 0.06097560975609756, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 10 + }, + "00113_00002-00202_00003" : { + "minimal_similarity" : 0.1317365269461078, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00126_00002-00192_00002" : { + "minimal_similarity" : 0.11724137931034483, + "maximum_similarity" : 0.1297709923664122, + "matched_token_number" : 17 + }, + "00031_00002-00155_00001" : { + "minimal_similarity" : 0.088, + "maximum_similarity" : 0.08870967741935484, + "matched_token_number" : 11 + }, + "00113_00002-00202_00002" : { + "minimal_similarity" : 0.1317365269461078, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00097_00002-00198_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00186_00002-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00013_00002-00121_00001" : { + "minimal_similarity" : 0.17616580310880828, + "maximum_similarity" : 0.2556390977443609, + "matched_token_number" : 34 + }, + "00138_00001-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00141_00002-00154_00002" : { + "minimal_similarity" : 0.2682926829268293, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00031_00003-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00111_00001-00194_00001" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00005_00002-00156_00003" : { + "minimal_similarity" : 0.047619047619047616, + "maximum_similarity" : 0.05056179775280899, + "matched_token_number" : 9 + }, + "00005_00002-00156_00002" : { + "minimal_similarity" : 0.047619047619047616, + "maximum_similarity" : 0.05056179775280899, + "matched_token_number" : 9 + }, + "00129_00008-00134_00001" : { + "minimal_similarity" : 0.08865248226950355, + "maximum_similarity" : 0.21367521367521367, + "matched_token_number" : 25 + }, + "00031_00002-00154_00002" : { + "minimal_similarity" : 0.06707317073170732, + "maximum_similarity" : 0.08870967741935484, + "matched_token_number" : 11 + }, + "00131_00005-00193_00001" : { + "minimal_similarity" : 0.12169312169312169, + "maximum_similarity" : 0.1393939393939394, + "matched_token_number" : 23 + }, + "00183_00004-00194_00001" : { + "minimal_similarity" : 0.07333333333333333, + "maximum_similarity" : 0.07482993197278912, + "matched_token_number" : 11 + }, + "00097_00002-00197_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00014_00001-00031_00002" : { + "minimal_similarity" : 0.07333333333333333, + "maximum_similarity" : 0.08870967741935484, + "matched_token_number" : 11 + }, + "00014_00001-00136_00002" : { + "minimal_similarity" : 0.1004566210045662, + "maximum_similarity" : 0.14666666666666667, + "matched_token_number" : 22 + }, + "00014_00001-00031_00003" : { + "minimal_similarity" : 0.16, + "maximum_similarity" : 0.21052631578947367, + "matched_token_number" : 24 + }, + "00044_00002-00199_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00178_00002-00202_00002" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00121_00001-00125_00001" : { + "minimal_similarity" : 0.7046632124352331, + "maximum_similarity" : 0.8095238095238095, + "matched_token_number" : 136 + }, + "00125_00001-00197_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.17424242424242425, + "matched_token_number" : 23 + }, + "00130_00002-00156_00003" : { + "minimal_similarity" : 0.06741573033707865, + "maximum_similarity" : 0.09022556390977443, + "matched_token_number" : 12 + }, + "00119_00001-00198_00001" : { + "minimal_similarity" : 0.10606060606060606, + "maximum_similarity" : 0.14, + "matched_token_number" : 21 + }, + "00134_00001-00135_00001" : { + "minimal_similarity" : 0.10869565217391304, + "maximum_similarity" : 0.17094017094017094, + "matched_token_number" : 20 + }, + "00130_00002-00156_00002" : { + "minimal_similarity" : 0.06741573033707865, + "maximum_similarity" : 0.09022556390977443, + "matched_token_number" : 12 + }, + "00184_00002-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00131_00005-00156_00002" : { + "minimal_similarity" : 0.047619047619047616, + "maximum_similarity" : 0.05056179775280899, + "matched_token_number" : 9 + }, + "00196_00001-00199_00001" : { + "minimal_similarity" : 0.024793388429752067, + "maximum_similarity" : 0.09473684210526316, + "matched_token_number" : 9 + }, + "00131_00005-00156_00003" : { + "minimal_similarity" : 0.047619047619047616, + "maximum_similarity" : 0.05056179775280899, + "matched_token_number" : 9 + }, + "00031_00002-00193_00001" : { + "minimal_similarity" : 0.05454545454545454, + "maximum_similarity" : 0.07258064516129033, + "matched_token_number" : 9 + }, + "00197_00001-00199_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00193_00001-00194_00001" : { + "minimal_similarity" : 0.07272727272727272, + "maximum_similarity" : 0.08, + "matched_token_number" : 12 + }, + "00113_00002-00187_00001" : { + "minimal_similarity" : 0.1377245508982036, + "maximum_similarity" : 0.17424242424242425, + "matched_token_number" : 23 + }, + "00000_00005-00204_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00031_00003-00113_00002" : { + "minimal_similarity" : 0.1437125748502994, + "maximum_similarity" : 0.21052631578947367, + "matched_token_number" : 24 + }, + "00097_00002-00156_00002" : { + "minimal_similarity" : 0.05056179775280899, + "maximum_similarity" : 0.060810810810810814, + "matched_token_number" : 9 + }, + "00097_00002-00156_00003" : { + "minimal_similarity" : 0.05056179775280899, + "maximum_similarity" : 0.060810810810810814, + "matched_token_number" : 9 + }, + "00120_00001-00160_00001" : { + "minimal_similarity" : 0.06206896551724138, + "maximum_similarity" : 0.0661764705882353, + "matched_token_number" : 9 + }, + "00111_00001-00121_00001" : { + "minimal_similarity" : 0.7046632124352331, + "maximum_similarity" : 0.8095238095238095, + "matched_token_number" : 136 + }, + "00198_00001-00199_00001" : { + "minimal_similarity" : 0.045454545454545456, + "maximum_similarity" : 0.09473684210526316, + "matched_token_number" : 9 + }, + "00155_00001-00201_00001" : { + "minimal_similarity" : 0.15384615384615385, + "maximum_similarity" : 0.16, + "matched_token_number" : 20 + }, + "00097_00002-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00001-00121_00001" : { + "minimal_similarity" : 0.12435233160621761, + "maximum_similarity" : 0.1889763779527559, + "matched_token_number" : 24 + }, + "00000_00001-00187_00001" : { + "minimal_similarity" : 0.25757575757575757, + "maximum_similarity" : 0.2677165354330709, + "matched_token_number" : 34 + }, + "00138_00001-00141_00002" : { + "minimal_similarity" : 0.1, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00000_00005-00147_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00095_00003-00111_00001" : { + "minimal_similarity" : 0.11386138613861387, + "maximum_similarity" : 0.13690476190476192, + "matched_token_number" : 23 + }, + "00125_00001-00131_00005" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00077_00001-00121_00001" : { + "minimal_similarity" : 0.09844559585492228, + "maximum_similarity" : 0.10052910052910052, + "matched_token_number" : 19 + }, + "00000_00002-00147_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00014_00001-00131_00005" : { + "minimal_similarity" : 0.1111111111111111, + "maximum_similarity" : 0.14, + "matched_token_number" : 21 + }, + "00130_00002-00183_00004" : { + "minimal_similarity" : 0.09523809523809523, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 14 + }, + "00121_00001-00192_00002" : { + "minimal_similarity" : 0.11917098445595854, + "maximum_similarity" : 0.17557251908396945, + "matched_token_number" : 23 + }, + "00121_00001-00192_00001" : { + "minimal_similarity" : 0.12953367875647667, + "maximum_similarity" : 0.16129032258064516, + "matched_token_number" : 25 + }, + "00178_00002-00202_00003" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00187_00001-00195_00002" : { + "minimal_similarity" : 0.08496732026143791, + "maximum_similarity" : 0.09848484848484848, + "matched_token_number" : 13 + }, + "00186_00002-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00187_00001-00195_00001" : { + "minimal_similarity" : 0.08496732026143791, + "maximum_similarity" : 0.09848484848484848, + "matched_token_number" : 13 + }, + "00192_00002-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00129_00008-00131_00005" : { + "minimal_similarity" : 0.03546099290780142, + "maximum_similarity" : 0.05291005291005291, + "matched_token_number" : 10 + }, + "00077_00001-00195_00001" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.13071895424836602, + "matched_token_number" : 20 + }, + "00077_00001-00195_00002" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.13071895424836602, + "matched_token_number" : 20 + }, + "00120_00001-00199_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00125_00001-00136_00002" : { + "minimal_similarity" : 0.0867579908675799, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00014_00001-00197_00001" : { + "minimal_similarity" : 0.08666666666666667, + "maximum_similarity" : 0.09848484848484848, + "matched_token_number" : 13 + }, + "00000_00005-00113_00002" : { + "minimal_similarity" : 0.0658682634730539, + "maximum_similarity" : 0.0738255033557047, + "matched_token_number" : 11 + }, + "00193_00001-00199_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00031_00003-00145_00001" : { + "minimal_similarity" : 0.14285714285714285, + "maximum_similarity" : 0.21052631578947367, + "matched_token_number" : 24 + }, + "00000_00002-00113_00002" : { + "minimal_similarity" : 0.11976047904191617, + "maximum_similarity" : 0.1388888888888889, + "matched_token_number" : 20 + }, + "00120_00001-00192_00001" : { + "minimal_similarity" : 0.08387096774193549, + "maximum_similarity" : 0.0896551724137931, + "matched_token_number" : 13 + }, + "00120_00001-00192_00002" : { + "minimal_similarity" : 0.11724137931034483, + "maximum_similarity" : 0.1297709923664122, + "matched_token_number" : 17 + }, + "00031_00002-00198_00001" : { + "minimal_similarity" : 0.12626262626262627, + "maximum_similarity" : 0.20161290322580644, + "matched_token_number" : 25 + }, + "00095_00003-00177_00003" : { + "minimal_similarity" : 0.11386138613861387, + "maximum_similarity" : 0.13690476190476192, + "matched_token_number" : 23 + }, + "00156_00003-00197_00001" : { + "minimal_similarity" : 0.05056179775280899, + "maximum_similarity" : 0.06818181818181818, + "matched_token_number" : 9 + }, + "00186_00004-00195_00001" : { + "minimal_similarity" : 0.10457516339869281, + "maximum_similarity" : 0.1111111111111111, + "matched_token_number" : 16 + }, + "00186_00004-00195_00002" : { + "minimal_similarity" : 0.10457516339869281, + "maximum_similarity" : 0.1111111111111111, + "matched_token_number" : 16 + }, + "00119_00001-00137_00002" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00000_00001-00153_00001" : { + "minimal_similarity" : 0.1488095238095238, + "maximum_similarity" : 0.1968503937007874, + "matched_token_number" : 25 + }, + "00113_00002-00147_00001" : { + "minimal_similarity" : 0.08982035928143713, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00000_00001-00126_00002" : { + "minimal_similarity" : 0.1724137931034483, + "maximum_similarity" : 0.1968503937007874, + "matched_token_number" : 25 + }, + "00195_00001-00199_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00137_00002-00194_00001" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00133_00001-00135_00001" : { + "minimal_similarity" : 0.1956521739130435, + "maximum_similarity" : 0.21428571428571427, + "matched_token_number" : 36 + }, + "00113_00002-00204_00001" : { + "minimal_similarity" : 0.1377245508982036, + "maximum_similarity" : 0.19166666666666668, + "matched_token_number" : 23 + }, + "00160_00001-00200_00002" : { + "minimal_similarity" : 0.06470588235294118, + "maximum_similarity" : 0.08088235294117647, + "matched_token_number" : 11 + }, + "00147_00001-00177_00003" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00000_00002-00142_00001" : { + "minimal_similarity" : 0.12418300653594772, + "maximum_similarity" : 0.13194444444444445, + "matched_token_number" : 19 + }, + "00077_00001-00126_00002" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.13793103448275862, + "matched_token_number" : 20 + }, + "00000_00005-00142_00001" : { + "minimal_similarity" : 0.06535947712418301, + "maximum_similarity" : 0.06711409395973154, + "matched_token_number" : 10 + }, + "00120_00001-00125_00001" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.2482758620689655, + "matched_token_number" : 36 + }, + "00121_00001-00197_00001" : { + "minimal_similarity" : 0.12953367875647667, + "maximum_similarity" : 0.1893939393939394, + "matched_token_number" : 25 + }, + "00031_00003-00204_00001" : { + "minimal_similarity" : 0.19166666666666668, + "maximum_similarity" : 0.20175438596491227, + "matched_token_number" : 23 + }, + "00136_00002-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00005_00002-00153_00001" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00005_00002-00113_00002" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.11377245508982035, + "matched_token_number" : 19 + }, + "00192_00001-00194_00001" : { + "minimal_similarity" : 0.08387096774193549, + "maximum_similarity" : 0.08666666666666667, + "matched_token_number" : 13 + }, + "00127_00002-00155_00001" : { + "minimal_similarity" : 0.30357142857142855, + "maximum_similarity" : 0.408, + "matched_token_number" : 51 + }, + "00013_00002-00155_00001" : { + "minimal_similarity" : 0.22556390977443608, + "maximum_similarity" : 0.24, + "matched_token_number" : 30 + }, + "00120_00001-00194_00001" : { + "minimal_similarity" : 0.31333333333333335, + "maximum_similarity" : 0.32413793103448274, + "matched_token_number" : 47 + }, + "00201_00001-00203_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00145_00001-00177_00003" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00097_00002-00127_00002" : { + "minimal_similarity" : 0.07738095238095238, + "maximum_similarity" : 0.08783783783783784, + "matched_token_number" : 13 + }, + "00031_00003-00147_00001" : { + "minimal_similarity" : 0.06944444444444445, + "maximum_similarity" : 0.08771929824561403, + "matched_token_number" : 10 + }, + "00186_00004-00197_00001" : { + "minimal_similarity" : 0.3333333333333333, + "maximum_similarity" : 0.36363636363636365, + "matched_token_number" : 48 + }, + "00136_00002-00199_00001" : { + "minimal_similarity" : 0.0410958904109589, + "maximum_similarity" : 0.09473684210526316, + "matched_token_number" : 9 + }, + "00160_00001-00202_00002" : { + "minimal_similarity" : 0.1347517730496454, + "maximum_similarity" : 0.13970588235294118, + "matched_token_number" : 19 + }, + "00120_00001-00197_00001" : { + "minimal_similarity" : 0.0896551724137931, + "maximum_similarity" : 0.09848484848484848, + "matched_token_number" : 13 + }, + "00147_00001-00204_00001" : { + "minimal_similarity" : 0.06944444444444445, + "maximum_similarity" : 0.08333333333333333, + "matched_token_number" : 10 + }, + "00111_00001-00153_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00156_00003-00192_00002" : { + "minimal_similarity" : 0.05056179775280899, + "maximum_similarity" : 0.06870229007633588, + "matched_token_number" : 9 + }, + "00156_00003-00195_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00156_00003-00195_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00155_00001-00178_00002" : { + "minimal_similarity" : 0.30357142857142855, + "maximum_similarity" : 0.408, + "matched_token_number" : 51 + }, + "00156_00003-00192_00001" : { + "minimal_similarity" : 0.05056179775280899, + "maximum_similarity" : 0.05806451612903226, + "matched_token_number" : 9 + }, + "00138_00001-00178_00002" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00125_00001-00160_00001" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.16176470588235295, + "matched_token_number" : 22 + }, + "00160_00001-00202_00003" : { + "minimal_similarity" : 0.1347517730496454, + "maximum_similarity" : 0.13970588235294118, + "matched_token_number" : 19 + }, + "00133_00001-00137_00002" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00121_00001-00199_00001" : { + "minimal_similarity" : 0.05181347150259067, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 10 + }, + "00127_00002-00192_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.14838709677419354, + "matched_token_number" : 23 + }, + "00127_00002-00192_00002" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.1984732824427481, + "matched_token_number" : 26 + }, + "00129_00008-00195_00001" : { + "minimal_similarity" : 0.0425531914893617, + "maximum_similarity" : 0.0784313725490196, + "matched_token_number" : 12 + }, + "00126_00002-00155_00001" : { + "minimal_similarity" : 0.2482758620689655, + "maximum_similarity" : 0.288, + "matched_token_number" : 36 + }, + "00129_00008-00195_00002" : { + "minimal_similarity" : 0.0425531914893617, + "maximum_similarity" : 0.0784313725490196, + "matched_token_number" : 12 + }, + "00136_00002-00160_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00153_00001-00203_00002" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.15862068965517243, + "matched_token_number" : 23 + }, + "00121_00001-00127_00002" : { + "minimal_similarity" : 0.7046632124352331, + "maximum_similarity" : 0.8095238095238095, + "matched_token_number" : 136 + }, + "00092_00001-00193_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00193_00001-00196_00001" : { + "minimal_similarity" : 0.024793388429752067, + "maximum_similarity" : 0.05454545454545454, + "matched_token_number" : 9 + }, + "00137_00002-00160_00001" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.16176470588235295, + "matched_token_number" : 22 + }, + "00031_00002-00121_00001" : { + "minimal_similarity" : 0.05699481865284974, + "maximum_similarity" : 0.08870967741935484, + "matched_token_number" : 11 + }, + "00141_00002-00195_00001" : { + "minimal_similarity" : 0.30718954248366015, + "maximum_similarity" : 0.31333333333333335, + "matched_token_number" : 47 + }, + "00044_00002-00134_00001" : { + "minimal_similarity" : 0.2426470588235294, + "maximum_similarity" : 0.28205128205128205, + "matched_token_number" : 33 + }, + "00141_00002-00195_00002" : { + "minimal_similarity" : 0.30718954248366015, + "maximum_similarity" : 0.31333333333333335, + "matched_token_number" : 47 + }, + "00111_00001-00155_00001" : { + "minimal_similarity" : 0.30357142857142855, + "maximum_similarity" : 0.408, + "matched_token_number" : 51 + }, + "00097_00002-00129_00008" : { + "minimal_similarity" : 0.05319148936170213, + "maximum_similarity" : 0.10135135135135136, + "matched_token_number" : 15 + }, + "00153_00001-00201_00001" : { + "minimal_similarity" : 0.05357142857142857, + "maximum_similarity" : 0.06923076923076923, + "matched_token_number" : 9 + }, + "00147_00001-00202_00003" : { + "minimal_similarity" : 0.08333333333333333, + "maximum_similarity" : 0.0851063829787234, + "matched_token_number" : 12 + }, + "00147_00001-00202_00002" : { + "minimal_similarity" : 0.08333333333333333, + "maximum_similarity" : 0.0851063829787234, + "matched_token_number" : 12 + }, + "00044_00002-00077_00001" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.13970588235294118, + "matched_token_number" : 19 + }, + "00178_00002-00200_00002" : { + "minimal_similarity" : 0.06470588235294118, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00000_00002-00140_00001" : { + "minimal_similarity" : 0.0625, + "maximum_similarity" : 0.06766917293233082, + "matched_token_number" : 9 + }, + "00121_00001-00160_00001" : { + "minimal_similarity" : 0.15544041450777202, + "maximum_similarity" : 0.22058823529411764, + "matched_token_number" : 30 + }, + "00141_00002-00193_00001" : { + "minimal_similarity" : 0.07272727272727272, + "maximum_similarity" : 0.08, + "matched_token_number" : 12 + }, + "00000_00005-00202_00002" : { + "minimal_similarity" : 0.15436241610738255, + "maximum_similarity" : 0.16312056737588654, + "matched_token_number" : 23 + }, + "00092_00001-00129_00008" : { + "minimal_similarity" : 0.031914893617021274, + "maximum_similarity" : 0.0625, + "matched_token_number" : 9 + }, + "00000_00005-00202_00003" : { + "minimal_similarity" : 0.1342281879194631, + "maximum_similarity" : 0.14184397163120568, + "matched_token_number" : 20 + }, + "00192_00002-00203_00002" : { + "minimal_similarity" : 0.31724137931034485, + "maximum_similarity" : 0.3511450381679389, + "matched_token_number" : 46 + }, + "00194_00001-00199_00001" : { + "minimal_similarity" : 0.06666666666666667, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 10 + }, + "00077_00001-00198_00001" : { + "minimal_similarity" : 0.050505050505050504, + "maximum_similarity" : 0.05291005291005291, + "matched_token_number" : 10 + }, + "00031_00002-00195_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00131_00005-00154_00002" : { + "minimal_similarity" : 0.1111111111111111, + "maximum_similarity" : 0.12804878048780488, + "matched_token_number" : 21 + }, + "00031_00002-00195_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00111_00001-00126_00002" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.2482758620689655, + "matched_token_number" : 36 + }, + "00187_00001-00197_00001" : { + "minimal_similarity" : 0.9772727272727273, + "maximum_similarity" : 0.9772727272727273, + "matched_token_number" : 129 + }, + "00000_00002-00111_00001" : { + "minimal_similarity" : 0.11904761904761904, + "maximum_similarity" : 0.1388888888888889, + "matched_token_number" : 20 + }, + "00125_00001-00133_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00119_00001-00134_00001" : { + "minimal_similarity" : 0.26, + "maximum_similarity" : 0.3333333333333333, + "matched_token_number" : 39 + }, + "00005_00002-00092_00001" : { + "minimal_similarity" : 0.09523809523809523, + "maximum_similarity" : 0.125, + "matched_token_number" : 18 + }, + "00013_00002-00184_00003" : { + "minimal_similarity" : 0.09774436090225563, + "maximum_similarity" : 0.13829787234042554, + "matched_token_number" : 13 + }, + "00013_00002-00184_00002" : { + "minimal_similarity" : 0.09774436090225563, + "maximum_similarity" : 0.13829787234042554, + "matched_token_number" : 13 + }, + "00044_00002-00136_00002" : { + "minimal_similarity" : 0.1780821917808219, + "maximum_similarity" : 0.2867647058823529, + "matched_token_number" : 39 + }, + "00129_00008-00197_00001" : { + "minimal_similarity" : 0.07446808510638298, + "maximum_similarity" : 0.1590909090909091, + "matched_token_number" : 21 + }, + "00000_00005-00145_00001" : { + "minimal_similarity" : 0.06547619047619048, + "maximum_similarity" : 0.0738255033557047, + "matched_token_number" : 11 + }, + "00147_00001-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00095_00003-00204_00001" : { + "minimal_similarity" : 0.0594059405940594, + "maximum_similarity" : 0.1, + "matched_token_number" : 12 + }, + "00129_00008-00199_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00077_00001-00197_00001" : { + "minimal_similarity" : 0.05291005291005291, + "maximum_similarity" : 0.07575757575757576, + "matched_token_number" : 10 + }, + "00126_00002-00154_00002" : { + "minimal_similarity" : 0.15853658536585366, + "maximum_similarity" : 0.1793103448275862, + "matched_token_number" : 26 + }, + "00134_00001-00138_00001" : { + "minimal_similarity" : 0.0763888888888889, + "maximum_similarity" : 0.09401709401709402, + "matched_token_number" : 11 + }, + "00092_00001-00194_00001" : { + "minimal_similarity" : 0.1, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00000_00005-00111_00001" : { + "minimal_similarity" : 0.06547619047619048, + "maximum_similarity" : 0.0738255033557047, + "matched_token_number" : 11 + }, + "00184_00002-00204_00001" : { + "minimal_similarity" : 0.19166666666666668, + "maximum_similarity" : 0.24468085106382978, + "matched_token_number" : 23 + }, + "00097_00002-00120_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00003-00131_00005" : { + "minimal_similarity" : 0.047619047619047616, + "maximum_similarity" : 0.060810810810810814, + "matched_token_number" : 9 + }, + "00136_00002-00192_00001" : { + "minimal_similarity" : 0.0867579908675799, + "maximum_similarity" : 0.12258064516129032, + "matched_token_number" : 19 + }, + "00136_00002-00192_00002" : { + "minimal_similarity" : 0.045662100456621, + "maximum_similarity" : 0.07633587786259542, + "matched_token_number" : 10 + }, + "00120_00001-00195_00002" : { + "minimal_similarity" : 0.9477124183006536, + "maximum_similarity" : 1.0, + "matched_token_number" : 145 + }, + "00120_00001-00195_00001" : { + "minimal_similarity" : 0.9477124183006536, + "maximum_similarity" : 1.0, + "matched_token_number" : 145 + }, + "00137_00002-00192_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.14838709677419354, + "matched_token_number" : 23 + }, + "00186_00004-00198_00001" : { + "minimal_similarity" : 0.06060606060606061, + "maximum_similarity" : 0.08333333333333333, + "matched_token_number" : 12 + }, + "00000_00001-00156_00002" : { + "minimal_similarity" : 0.05056179775280899, + "maximum_similarity" : 0.07086614173228346, + "matched_token_number" : 9 + }, + "00129_00008-00160_00001" : { + "minimal_similarity" : 0.031914893617021274, + "maximum_similarity" : 0.0661764705882353, + "matched_token_number" : 9 + }, + "00000_00001-00156_00003" : { + "minimal_similarity" : 0.05056179775280899, + "maximum_similarity" : 0.07086614173228346, + "matched_token_number" : 9 + }, + "00194_00001-00197_00001" : { + "minimal_similarity" : 0.08666666666666667, + "maximum_similarity" : 0.09848484848484848, + "matched_token_number" : 13 + }, + "00187_00001-00192_00001" : { + "minimal_similarity" : 0.5806451612903226, + "maximum_similarity" : 0.6818181818181818, + "matched_token_number" : 90 + }, + "00187_00001-00192_00002" : { + "minimal_similarity" : 0.49242424242424243, + "maximum_similarity" : 0.4961832061068702, + "matched_token_number" : 65 + }, + "00137_00002-00192_00002" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.1984732824427481, + "matched_token_number" : 26 + }, + "00013_00002-00154_00002" : { + "minimal_similarity" : 0.18292682926829268, + "maximum_similarity" : 0.22556390977443608, + "matched_token_number" : 30 + }, + "00136_00002-00198_00001" : { + "minimal_similarity" : 0.0410958904109589, + "maximum_similarity" : 0.045454545454545456, + "matched_token_number" : 9 + }, + "00119_00001-00130_00002" : { + "minimal_similarity" : 0.32666666666666666, + "maximum_similarity" : 0.3684210526315789, + "matched_token_number" : 49 + }, + "00135_00001-00137_00002" : { + "minimal_similarity" : 0.1956521739130435, + "maximum_similarity" : 0.21428571428571427, + "matched_token_number" : 36 + }, + "00121_00001-00195_00001" : { + "minimal_similarity" : 0.17098445595854922, + "maximum_similarity" : 0.21568627450980393, + "matched_token_number" : 33 + }, + "00130_00002-00186_00002" : { + "minimal_similarity" : 0.2159090909090909, + "maximum_similarity" : 0.2857142857142857, + "matched_token_number" : 38 + }, + "00121_00001-00195_00002" : { + "minimal_similarity" : 0.17098445595854922, + "maximum_similarity" : 0.21568627450980393, + "matched_token_number" : 33 + }, + "00195_00001-00197_00001" : { + "minimal_similarity" : 0.08496732026143791, + "maximum_similarity" : 0.09848484848484848, + "matched_token_number" : 13 + }, + "00000_00002-00202_00002" : { + "minimal_similarity" : 0.1597222222222222, + "maximum_similarity" : 0.16312056737588654, + "matched_token_number" : 23 + }, + "00005_00002-00183_00004" : { + "minimal_similarity" : 0.09523809523809523, + "maximum_similarity" : 0.12244897959183673, + "matched_token_number" : 18 + }, + "00130_00002-00186_00004" : { + "minimal_similarity" : 0.3472222222222222, + "maximum_similarity" : 0.37593984962406013, + "matched_token_number" : 50 + }, + "00155_00001-00204_00001" : { + "minimal_similarity" : 0.216, + "maximum_similarity" : 0.225, + "matched_token_number" : 27 + }, + "00160_00001-00178_00002" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.16176470588235295, + "matched_token_number" : 22 + }, + "00000_00002-00202_00003" : { + "minimal_similarity" : 0.1388888888888889, + "maximum_similarity" : 0.14184397163120568, + "matched_token_number" : 20 + }, + "00000_00003-00130_00002" : { + "minimal_similarity" : 0.060810810810810814, + "maximum_similarity" : 0.06766917293233082, + "matched_token_number" : 9 + }, + "00013_00002-00095_00003" : { + "minimal_similarity" : 0.04950495049504951, + "maximum_similarity" : 0.07518796992481203, + "matched_token_number" : 10 + }, + "00194_00001-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00130_00002-00154_00002" : { + "minimal_similarity" : 0.4146341463414634, + "maximum_similarity" : 0.5112781954887218, + "matched_token_number" : 68 + }, + "00184_00002-00203_00002" : { + "minimal_similarity" : 0.09655172413793103, + "maximum_similarity" : 0.14893617021276595, + "matched_token_number" : 14 + }, + "00178_00002-00204_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.19166666666666668, + "matched_token_number" : 23 + }, + "00187_00001-00193_00001" : { + "minimal_similarity" : 0.11515151515151516, + "maximum_similarity" : 0.14393939393939395, + "matched_token_number" : 19 + }, + "00092_00001-00195_00001" : { + "minimal_similarity" : 0.11764705882352941, + "maximum_similarity" : 0.125, + "matched_token_number" : 18 + }, + "00092_00001-00195_00002" : { + "minimal_similarity" : 0.11764705882352941, + "maximum_similarity" : 0.125, + "matched_token_number" : 18 + }, + "00130_00002-00187_00001" : { + "minimal_similarity" : 0.09774436090225563, + "maximum_similarity" : 0.09848484848484848, + "matched_token_number" : 13 + }, + "00095_00003-00140_00001" : { + "minimal_similarity" : 0.0594059405940594, + "maximum_similarity" : 0.09022556390977443, + "matched_token_number" : 12 + }, + "00077_00001-00125_00001" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00013_00002-00153_00001" : { + "minimal_similarity" : 0.18452380952380953, + "maximum_similarity" : 0.23308270676691728, + "matched_token_number" : 31 + }, + "00097_00002-00125_00001" : { + "minimal_similarity" : 0.07738095238095238, + "maximum_similarity" : 0.08783783783783784, + "matched_token_number" : 13 + }, + "00095_00003-00147_00001" : { + "minimal_similarity" : 0.054455445544554455, + "maximum_similarity" : 0.0763888888888889, + "matched_token_number" : 11 + }, + "00014_00001-00160_00001" : { + "minimal_similarity" : 0.08, + "maximum_similarity" : 0.08823529411764706, + "matched_token_number" : 12 + }, + "00013_00002-00186_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00147_00001-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00196_00001-00197_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00136_00002-00197_00001" : { + "minimal_similarity" : 0.045662100456621, + "maximum_similarity" : 0.07575757575757576, + "matched_token_number" : 10 + }, + "00121_00001-00196_00001" : { + "minimal_similarity" : 0.027548209366391185, + "maximum_similarity" : 0.05181347150259067, + "matched_token_number" : 10 + }, + "00000_00003-00136_00002" : { + "minimal_similarity" : 0.0410958904109589, + "maximum_similarity" : 0.060810810810810814, + "matched_token_number" : 9 + }, + "00013_00002-00186_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00044_00002-00133_00001" : { + "minimal_similarity" : 0.16071428571428573, + "maximum_similarity" : 0.19852941176470587, + "matched_token_number" : 27 + }, + "00000_00002-00201_00001" : { + "minimal_similarity" : 0.0625, + "maximum_similarity" : 0.06923076923076923, + "matched_token_number" : 9 + }, + "00097_00002-00126_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00013_00002-00187_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00095_00003-00141_00002" : { + "minimal_similarity" : 0.10891089108910891, + "maximum_similarity" : 0.14666666666666667, + "matched_token_number" : 22 + }, + "00031_00003-00111_00001" : { + "minimal_similarity" : 0.14285714285714285, + "maximum_similarity" : 0.21052631578947367, + "matched_token_number" : 24 + }, + "00092_00001-00160_00001" : { + "minimal_similarity" : 0.1527777777777778, + "maximum_similarity" : 0.16176470588235295, + "matched_token_number" : 22 + }, + "00000_00003-00137_00002" : { + "minimal_similarity" : 0.11904761904761904, + "maximum_similarity" : 0.13513513513513514, + "matched_token_number" : 20 + }, + "00031_00002-00129_00008" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00130_00002-00153_00001" : { + "minimal_similarity" : 0.3630952380952381, + "maximum_similarity" : 0.45864661654135336, + "matched_token_number" : 61 + }, + "00000_00002-00145_00001" : { + "minimal_similarity" : 0.11904761904761904, + "maximum_similarity" : 0.1388888888888889, + "matched_token_number" : 20 + }, + "00000_00003-00135_00001" : { + "minimal_similarity" : 0.10869565217391304, + "maximum_similarity" : 0.13513513513513514, + "matched_token_number" : 20 + }, + "00195_00001-00195_00002" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 153 + }, + "00000_00001-00155_00001" : { + "minimal_similarity" : 0.11023622047244094, + "maximum_similarity" : 0.112, + "matched_token_number" : 14 + }, + "00111_00001-00120_00001" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.2482758620689655, + "matched_token_number" : 36 + }, + "00031_00002-00127_00002" : { + "minimal_similarity" : 0.06547619047619048, + "maximum_similarity" : 0.08870967741935484, + "matched_token_number" : 11 + }, + "00155_00001-00200_00002" : { + "minimal_similarity" : 0.08823529411764706, + "maximum_similarity" : 0.12, + "matched_token_number" : 15 + }, + "00137_00002-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00133_00001-00134_00001" : { + "minimal_similarity" : 0.1488095238095238, + "maximum_similarity" : 0.21367521367521367, + "matched_token_number" : 25 + }, + "00005_00002-00184_00002" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.20212765957446807, + "matched_token_number" : 19 + }, + "00121_00001-00129_00008" : { + "minimal_similarity" : 0.10638297872340426, + "maximum_similarity" : 0.15544041450777202, + "matched_token_number" : 30 + }, + "00000_00002-00203_00002" : { + "minimal_similarity" : 0.12413793103448276, + "maximum_similarity" : 0.125, + "matched_token_number" : 18 + }, + "00005_00002-00184_00003" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.20212765957446807, + "matched_token_number" : 19 + }, + "00077_00001-00193_00001" : { + "minimal_similarity" : 0.12169312169312169, + "maximum_similarity" : 0.1393939393939394, + "matched_token_number" : 23 + }, + "00095_00003-00142_00001" : { + "minimal_similarity" : 0.0594059405940594, + "maximum_similarity" : 0.0784313725490196, + "matched_token_number" : 12 + }, + "00095_00003-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00160_00001-00177_00003" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.16176470588235295, + "matched_token_number" : 22 + }, + "00195_00001-00198_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00097_00002-00121_00001" : { + "minimal_similarity" : 0.06735751295336788, + "maximum_similarity" : 0.08783783783783784, + "matched_token_number" : 13 + }, + "00137_00002-00199_00001" : { + "minimal_similarity" : 0.05952380952380952, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 10 + }, + "00005_00002-00187_00001" : { + "minimal_similarity" : 0.05291005291005291, + "maximum_similarity" : 0.07575757575757576, + "matched_token_number" : 10 + }, + "00196_00001-00198_00001" : { + "minimal_similarity" : 0.027548209366391185, + "maximum_similarity" : 0.050505050505050504, + "matched_token_number" : 10 + }, + "00120_00001-00127_00002" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.2482758620689655, + "matched_token_number" : 36 + }, + "00092_00001-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00120_00001-00129_00008" : { + "minimal_similarity" : 0.0425531914893617, + "maximum_similarity" : 0.08275862068965517, + "matched_token_number" : 12 + }, + "00013_00002-00092_00001" : { + "minimal_similarity" : 0.06944444444444445, + "maximum_similarity" : 0.07518796992481203, + "matched_token_number" : 10 + }, + "00044_00002-00131_00005" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.13970588235294118, + "matched_token_number" : 19 + }, + "00000_00001-00097_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00186_00004-00194_00001" : { + "minimal_similarity" : 0.17333333333333334, + "maximum_similarity" : 0.18055555555555555, + "matched_token_number" : 26 + }, + "00134_00001-00137_00002" : { + "minimal_similarity" : 0.1488095238095238, + "maximum_similarity" : 0.21367521367521367, + "matched_token_number" : 25 + }, + "00000_00003-00077_00001" : { + "minimal_similarity" : 0.047619047619047616, + "maximum_similarity" : 0.060810810810810814, + "matched_token_number" : 9 + }, + "00186_00004-00192_00002" : { + "minimal_similarity" : 0.4097222222222222, + "maximum_similarity" : 0.45038167938931295, + "matched_token_number" : 59 + }, + "00186_00004-00192_00001" : { + "minimal_similarity" : 0.3096774193548387, + "maximum_similarity" : 0.3333333333333333, + "matched_token_number" : 48 + }, + "00155_00001-00202_00002" : { + "minimal_similarity" : 0.1702127659574468, + "maximum_similarity" : 0.192, + "matched_token_number" : 24 + }, + "00155_00001-00202_00003" : { + "minimal_similarity" : 0.1702127659574468, + "maximum_similarity" : 0.192, + "matched_token_number" : 24 + }, + "00121_00001-00193_00001" : { + "minimal_similarity" : 0.046632124352331605, + "maximum_similarity" : 0.05454545454545454, + "matched_token_number" : 9 + }, + "00077_00001-00129_00008" : { + "minimal_similarity" : 0.03546099290780142, + "maximum_similarity" : 0.05291005291005291, + "matched_token_number" : 10 + }, + "00005_00002-00186_00004" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.1388888888888889, + "matched_token_number" : 20 + }, + "00092_00001-00199_00001" : { + "minimal_similarity" : 0.06944444444444445, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 10 + }, + "00137_00002-00198_00001" : { + "minimal_similarity" : 0.18686868686868688, + "maximum_similarity" : 0.22023809523809523, + "matched_token_number" : 37 + }, + "00005_00002-00186_00002" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.11363636363636363, + "matched_token_number" : 20 + }, + "00136_00002-00194_00001" : { + "minimal_similarity" : 0.1004566210045662, + "maximum_similarity" : 0.14666666666666667, + "matched_token_number" : 22 + }, + "00077_00001-00192_00001" : { + "minimal_similarity" : 0.05291005291005291, + "maximum_similarity" : 0.06451612903225806, + "matched_token_number" : 10 + }, + "00077_00001-00192_00002" : { + "minimal_similarity" : 0.05291005291005291, + "maximum_similarity" : 0.07633587786259542, + "matched_token_number" : 10 + }, + "00095_00003-00202_00002" : { + "minimal_similarity" : 0.09405940594059406, + "maximum_similarity" : 0.1347517730496454, + "matched_token_number" : 19 + }, + "00000_00003-00133_00001" : { + "minimal_similarity" : 0.11904761904761904, + "maximum_similarity" : 0.13513513513513514, + "matched_token_number" : 20 + }, + "00095_00003-00202_00003" : { + "minimal_similarity" : 0.09405940594059406, + "maximum_similarity" : 0.1347517730496454, + "matched_token_number" : 19 + }, + "00135_00001-00138_00001" : { + "minimal_similarity" : 0.08152173913043478, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00134_00001-00136_00002" : { + "minimal_similarity" : 0.0410958904109589, + "maximum_similarity" : 0.07692307692307693, + "matched_token_number" : 9 + }, + "00031_00002-00125_00001" : { + "minimal_similarity" : 0.06547619047619048, + "maximum_similarity" : 0.08870967741935484, + "matched_token_number" : 11 + }, + "00155_00001-00203_00002" : { + "minimal_similarity" : 0.1103448275862069, + "maximum_similarity" : 0.128, + "matched_token_number" : 16 + }, + "00092_00001-00198_00001" : { + "minimal_similarity" : 0.050505050505050504, + "maximum_similarity" : 0.06944444444444445, + "matched_token_number" : 10 + }, + "00121_00001-00194_00001" : { + "minimal_similarity" : 0.27461139896373055, + "maximum_similarity" : 0.35333333333333333, + "matched_token_number" : 53 + }, + "00095_00003-00145_00001" : { + "minimal_similarity" : 0.11386138613861387, + "maximum_similarity" : 0.13690476190476192, + "matched_token_number" : 23 + }, + "00000_00003-00134_00001" : { + "minimal_similarity" : 0.060810810810810814, + "maximum_similarity" : 0.07692307692307693, + "matched_token_number" : 9 + }, + "00186_00004-00193_00001" : { + "minimal_similarity" : 0.2, + "maximum_similarity" : 0.22916666666666666, + "matched_token_number" : 33 + }, + "00095_00003-00203_00002" : { + "minimal_similarity" : 0.0594059405940594, + "maximum_similarity" : 0.08275862068965517, + "matched_token_number" : 12 + }, + "00195_00001-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00137_00002-00197_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.17424242424242425, + "matched_token_number" : 23 + }, + "00000_00002-00204_00001" : { + "minimal_similarity" : 0.0625, + "maximum_similarity" : 0.075, + "matched_token_number" : 9 + }, + "00153_00001-00178_00002" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00031_00002-00126_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00136_00002-00193_00001" : { + "minimal_similarity" : 0.0502283105022831, + "maximum_similarity" : 0.06666666666666667, + "matched_token_number" : 11 + }, + "00134_00001-00155_00001" : { + "minimal_similarity" : 0.704, + "maximum_similarity" : 0.7521367521367521, + "matched_token_number" : 88 + }, + "00130_00002-00201_00001" : { + "minimal_similarity" : 0.06766917293233082, + "maximum_similarity" : 0.06923076923076923, + "matched_token_number" : 9 + }, + "00121_00001-00145_00001" : { + "minimal_similarity" : 0.7046632124352331, + "maximum_similarity" : 0.8095238095238095, + "matched_token_number" : 136 + }, + "00000_00001-00119_00001" : { + "minimal_similarity" : 0.18, + "maximum_similarity" : 0.2125984251968504, + "matched_token_number" : 27 + }, + "00140_00001-00141_00002" : { + "minimal_similarity" : 0.32666666666666666, + "maximum_similarity" : 0.3684210526315789, + "matched_token_number" : 49 + }, + "00131_00005-00136_00002" : { + "minimal_similarity" : 0.1050228310502283, + "maximum_similarity" : 0.12169312169312169, + "matched_token_number" : 23 + }, + "00113_00002-00154_00002" : { + "minimal_similarity" : 0.8862275449101796, + "maximum_similarity" : 0.9024390243902439, + "matched_token_number" : 148 + }, + "00000_00003-00119_00001" : { + "minimal_similarity" : 0.13333333333333333, + "maximum_similarity" : 0.13513513513513514, + "matched_token_number" : 20 + }, + "00000_00005-00119_00001" : { + "minimal_similarity" : 0.07333333333333333, + "maximum_similarity" : 0.0738255033557047, + "matched_token_number" : 11 + }, + "00092_00001-00184_00002" : { + "minimal_similarity" : 0.06944444444444445, + "maximum_similarity" : 0.10638297872340426, + "matched_token_number" : 10 + }, + "00044_00002-00183_00004" : { + "minimal_similarity" : 0.06802721088435375, + "maximum_similarity" : 0.07352941176470588, + "matched_token_number" : 10 + }, + "00092_00001-00184_00003" : { + "minimal_similarity" : 0.06944444444444445, + "maximum_similarity" : 0.10638297872340426, + "matched_token_number" : 10 + }, + "00202_00003-00204_00001" : { + "minimal_similarity" : 0.3120567375886525, + "maximum_similarity" : 0.36666666666666664, + "matched_token_number" : 44 + }, + "00127_00002-00129_00008" : { + "minimal_similarity" : 0.10638297872340426, + "maximum_similarity" : 0.17857142857142858, + "matched_token_number" : 30 + }, + "00129_00008-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00197_00001-00204_00001" : { + "minimal_similarity" : 0.3939393939393939, + "maximum_similarity" : 0.43333333333333335, + "matched_token_number" : 52 + }, + "00031_00003-00160_00001" : { + "minimal_similarity" : 0.0661764705882353, + "maximum_similarity" : 0.07894736842105263, + "matched_token_number" : 9 + }, + "00153_00001-00177_00003" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00145_00001-00178_00002" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00031_00003-00203_00002" : { + "minimal_similarity" : 0.16551724137931034, + "maximum_similarity" : 0.21052631578947367, + "matched_token_number" : 24 + }, + "00013_00002-00111_00001" : { + "minimal_similarity" : 0.18452380952380953, + "maximum_similarity" : 0.23308270676691728, + "matched_token_number" : 31 + }, + "00077_00001-00141_00002" : { + "minimal_similarity" : 0.1111111111111111, + "maximum_similarity" : 0.14, + "matched_token_number" : 21 + }, + "00156_00002-00183_00004" : { + "minimal_similarity" : 0.06741573033707865, + "maximum_similarity" : 0.08163265306122448, + "matched_token_number" : 12 + }, + "00136_00002-00155_00001" : { + "minimal_similarity" : 0.0867579908675799, + "maximum_similarity" : 0.152, + "matched_token_number" : 19 + }, + "00137_00002-00187_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.17424242424242425, + "matched_token_number" : 23 + }, + "00097_00002-00136_00002" : { + "minimal_similarity" : 0.0410958904109589, + "maximum_similarity" : 0.060810810810810814, + "matched_token_number" : 9 + }, + "00160_00001-00195_00002" : { + "minimal_similarity" : 0.058823529411764705, + "maximum_similarity" : 0.0661764705882353, + "matched_token_number" : 9 + }, + "00000_00002-00199_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00160_00001-00195_00001" : { + "minimal_similarity" : 0.058823529411764705, + "maximum_similarity" : 0.0661764705882353, + "matched_token_number" : 9 + }, + "00031_00002-00199_00001" : { + "minimal_similarity" : 0.0967741935483871, + "maximum_similarity" : 0.12631578947368421, + "matched_token_number" : 12 + }, + "00195_00002-00204_00001" : { + "minimal_similarity" : 0.08496732026143791, + "maximum_similarity" : 0.10833333333333334, + "matched_token_number" : 13 + }, + "00125_00001-00129_00008" : { + "minimal_similarity" : 0.10638297872340426, + "maximum_similarity" : 0.17857142857142858, + "matched_token_number" : 30 + }, + "00147_00001-00160_00001" : { + "minimal_similarity" : 0.1527777777777778, + "maximum_similarity" : 0.16176470588235295, + "matched_token_number" : 22 + }, + "00000_00002-00127_00002" : { + "minimal_similarity" : 0.11904761904761904, + "maximum_similarity" : 0.1388888888888889, + "matched_token_number" : 20 + }, + "00095_00003-00131_00005" : { + "minimal_similarity" : 0.04950495049504951, + "maximum_similarity" : 0.05291005291005291, + "matched_token_number" : 10 + }, + "00005_00002-00138_00001" : { + "minimal_similarity" : 0.09523809523809523, + "maximum_similarity" : 0.125, + "matched_token_number" : 18 + }, + "00135_00001-00187_00001" : { + "minimal_similarity" : 0.04891304347826087, + "maximum_similarity" : 0.06818181818181818, + "matched_token_number" : 9 + }, + "00200_00002-00204_00001" : { + "minimal_similarity" : 0.12941176470588237, + "maximum_similarity" : 0.18333333333333332, + "matched_token_number" : 22 + }, + "00121_00001-00140_00001" : { + "minimal_similarity" : 0.23834196891191708, + "maximum_similarity" : 0.3458646616541353, + "matched_token_number" : 46 + }, + "00000_00001-00160_00001" : { + "minimal_similarity" : 0.07352941176470588, + "maximum_similarity" : 0.07874015748031496, + "matched_token_number" : 10 + }, + "00000_00003-00160_00001" : { + "minimal_similarity" : 0.06756756756756757, + "maximum_similarity" : 0.07352941176470588, + "matched_token_number" : 10 + }, + "00193_00001-00204_00001" : { + "minimal_similarity" : 0.06060606060606061, + "maximum_similarity" : 0.08333333333333333, + "matched_token_number" : 10 + }, + "00077_00001-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00141_00002-00186_00004" : { + "minimal_similarity" : 0.17333333333333334, + "maximum_similarity" : 0.18055555555555555, + "matched_token_number" : 26 + }, + "00154_00002-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00141_00002-00186_00002" : { + "minimal_similarity" : 0.1534090909090909, + "maximum_similarity" : 0.18, + "matched_token_number" : 27 + }, + "00014_00001-00092_00001" : { + "minimal_similarity" : 0.1, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00031_00003-00186_00002" : { + "minimal_similarity" : 0.1590909090909091, + "maximum_similarity" : 0.24561403508771928, + "matched_token_number" : 28 + }, + "00140_00001-00200_00002" : { + "minimal_similarity" : 0.10588235294117647, + "maximum_similarity" : 0.13533834586466165, + "matched_token_number" : 18 + }, + "00126_00002-00202_00002" : { + "minimal_similarity" : 0.06896551724137931, + "maximum_similarity" : 0.07092198581560284, + "matched_token_number" : 10 + }, + "00000_00002-00194_00001" : { + "minimal_similarity" : 0.13333333333333333, + "maximum_similarity" : 0.1388888888888889, + "matched_token_number" : 20 + }, + "00129_00008-00137_00002" : { + "minimal_similarity" : 0.10638297872340426, + "maximum_similarity" : 0.17857142857142858, + "matched_token_number" : 30 + }, + "00126_00002-00202_00003" : { + "minimal_similarity" : 0.06896551724137931, + "maximum_similarity" : 0.07092198581560284, + "matched_token_number" : 10 + }, + "00121_00001-00204_00001" : { + "minimal_similarity" : 0.13989637305699482, + "maximum_similarity" : 0.225, + "matched_token_number" : 27 + }, + "00184_00002-00202_00002" : { + "minimal_similarity" : 0.14893617021276595, + "maximum_similarity" : 0.22340425531914893, + "matched_token_number" : 21 + }, + "00184_00002-00202_00003" : { + "minimal_similarity" : 0.14893617021276595, + "maximum_similarity" : 0.22340425531914893, + "matched_token_number" : 21 + }, + "00129_00008-00200_00002" : { + "minimal_similarity" : 0.03546099290780142, + "maximum_similarity" : 0.058823529411764705, + "matched_token_number" : 10 + }, + "00097_00002-00131_00005" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00031_00003-00186_00004" : { + "minimal_similarity" : 0.18055555555555555, + "maximum_similarity" : 0.22807017543859648, + "matched_token_number" : 26 + }, + "00142_00001-00154_00002" : { + "minimal_similarity" : 0.15853658536585366, + "maximum_similarity" : 0.16993464052287582, + "matched_token_number" : 26 + }, + "00145_00001-00199_00001" : { + "minimal_similarity" : 0.05952380952380952, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 10 + }, + "00092_00001-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00135_00001-00136_00002" : { + "minimal_similarity" : 0.0410958904109589, + "maximum_similarity" : 0.04891304347826087, + "matched_token_number" : 9 + }, + "00005_00002-00095_00003" : { + "minimal_similarity" : 0.04950495049504951, + "maximum_similarity" : 0.05291005291005291, + "matched_token_number" : 10 + }, + "00119_00001-00138_00001" : { + "minimal_similarity" : 0.1, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00153_00001-00198_00001" : { + "minimal_similarity" : 0.18686868686868688, + "maximum_similarity" : 0.22023809523809523, + "matched_token_number" : 37 + }, + "00014_00001-00156_00003" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.07333333333333333, + "matched_token_number" : 11 + }, + "00014_00001-00156_00002" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.07333333333333333, + "matched_token_number" : 11 + }, + "00092_00001-00138_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 144 + }, + "00095_00003-00136_00002" : { + "minimal_similarity" : 0.0867579908675799, + "maximum_similarity" : 0.09405940594059406, + "matched_token_number" : 19 + }, + "00156_00003-00196_00001" : { + "minimal_similarity" : 0.049586776859504134, + "maximum_similarity" : 0.10112359550561797, + "matched_token_number" : 18 + }, + "00044_00002-00137_00002" : { + "minimal_similarity" : 0.16071428571428573, + "maximum_similarity" : 0.19852941176470587, + "matched_token_number" : 27 + }, + "00141_00002-00203_00002" : { + "minimal_similarity" : 0.15333333333333332, + "maximum_similarity" : 0.15862068965517243, + "matched_token_number" : 23 + }, + "00177_00003-00201_00001" : { + "minimal_similarity" : 0.05357142857142857, + "maximum_similarity" : 0.06923076923076923, + "matched_token_number" : 9 + }, + "00000_00003-00203_00002" : { + "minimal_similarity" : 0.12162162162162163, + "maximum_similarity" : 0.12413793103448276, + "matched_token_number" : 18 + }, + "00119_00001-00184_00003" : { + "minimal_similarity" : 0.18, + "maximum_similarity" : 0.2872340425531915, + "matched_token_number" : 27 + }, + "00111_00001-00133_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00119_00001-00184_00002" : { + "minimal_similarity" : 0.18, + "maximum_similarity" : 0.2872340425531915, + "matched_token_number" : 27 + }, + "00000_00001-00203_00002" : { + "minimal_similarity" : 0.15172413793103448, + "maximum_similarity" : 0.1732283464566929, + "matched_token_number" : 22 + }, + "00000_00002-00178_00002" : { + "minimal_similarity" : 0.11904761904761904, + "maximum_similarity" : 0.1388888888888889, + "matched_token_number" : 20 + }, + "00014_00001-00097_00002" : { + "minimal_similarity" : 0.18666666666666668, + "maximum_similarity" : 0.1891891891891892, + "matched_token_number" : 28 + }, + "00125_00001-00140_00001" : { + "minimal_similarity" : 0.3630952380952381, + "maximum_similarity" : 0.45864661654135336, + "matched_token_number" : 61 + }, + "00077_00001-00120_00001" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.13793103448275862, + "matched_token_number" : 20 + }, + "00120_00001-00202_00003" : { + "minimal_similarity" : 0.06896551724137931, + "maximum_similarity" : 0.07092198581560284, + "matched_token_number" : 10 + }, + "00014_00001-00198_00001" : { + "minimal_similarity" : 0.10606060606060606, + "maximum_similarity" : 0.14, + "matched_token_number" : 21 + }, + "00120_00001-00202_00002" : { + "minimal_similarity" : 0.06896551724137931, + "maximum_similarity" : 0.07092198581560284, + "matched_token_number" : 10 + }, + "00095_00003-00178_00002" : { + "minimal_similarity" : 0.11386138613861387, + "maximum_similarity" : 0.13690476190476192, + "matched_token_number" : 23 + }, + "00005_00002-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00097_00002-00187_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00044_00002-00111_00001" : { + "minimal_similarity" : 0.16071428571428573, + "maximum_similarity" : 0.19852941176470587, + "matched_token_number" : 27 + }, + "00134_00001-00197_00001" : { + "minimal_similarity" : 0.08333333333333333, + "maximum_similarity" : 0.09401709401709402, + "matched_token_number" : 11 + }, + "00113_00002-00133_00001" : { + "minimal_similarity" : 0.9940476190476191, + "maximum_similarity" : 1.0, + "matched_token_number" : 167 + }, + "00137_00002-00140_00001" : { + "minimal_similarity" : 0.3630952380952381, + "maximum_similarity" : 0.45864661654135336, + "matched_token_number" : 61 + }, + "00131_00005-00178_00002" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00092_00001-00133_00001" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00119_00001-00133_00001" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00153_00001-00193_00001" : { + "minimal_similarity" : 0.07142857142857142, + "maximum_similarity" : 0.07272727272727272, + "matched_token_number" : 12 + }, + "00031_00003-00119_00001" : { + "minimal_similarity" : 0.16, + "maximum_similarity" : 0.21052631578947367, + "matched_token_number" : 24 + }, + "00130_00002-00184_00003" : { + "minimal_similarity" : 0.12030075187969924, + "maximum_similarity" : 0.1702127659574468, + "matched_token_number" : 16 + }, + "00130_00002-00184_00002" : { + "minimal_similarity" : 0.12030075187969924, + "maximum_similarity" : 0.1702127659574468, + "matched_token_number" : 16 + }, + "00187_00001-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00127_00002-00140_00001" : { + "minimal_similarity" : 0.3630952380952381, + "maximum_similarity" : 0.45864661654135336, + "matched_token_number" : 61 + }, + "00013_00002-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00014_00001-00177_00003" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00031_00003-00097_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00044_00002-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00014_00001-00130_00002" : { + "minimal_similarity" : 0.32666666666666666, + "maximum_similarity" : 0.3684210526315789, + "matched_token_number" : 49 + }, + "00138_00001-00155_00001" : { + "minimal_similarity" : 0.10416666666666667, + "maximum_similarity" : 0.12, + "matched_token_number" : 15 + }, + "00192_00002-00198_00001" : { + "minimal_similarity" : 0.06565656565656566, + "maximum_similarity" : 0.09923664122137404, + "matched_token_number" : 13 + }, + "00000_00005-00092_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00178_00002-00194_00001" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00044_00002-00141_00002" : { + "minimal_similarity" : 0.18, + "maximum_similarity" : 0.19852941176470587, + "matched_token_number" : 27 + }, + "00111_00001-00154_00002" : { + "minimal_similarity" : 0.8809523809523809, + "maximum_similarity" : 0.9024390243902439, + "matched_token_number" : 148 + }, + "00133_00001-00195_00001" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00133_00001-00195_00002" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00147_00001-00203_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00184_00003-00198_00001" : { + "minimal_similarity" : 0.045454545454545456, + "maximum_similarity" : 0.09574468085106383, + "matched_token_number" : 9 + }, + "00194_00001-00198_00001" : { + "minimal_similarity" : 0.10606060606060606, + "maximum_similarity" : 0.14, + "matched_token_number" : 21 + }, + "00000_00001-00092_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00160_00001-00203_00002" : { + "minimal_similarity" : 0.12413793103448276, + "maximum_similarity" : 0.1323529411764706, + "matched_token_number" : 18 + }, + "00031_00002-00194_00001" : { + "minimal_similarity" : 0.07333333333333333, + "maximum_similarity" : 0.08870967741935484, + "matched_token_number" : 11 + }, + "00000_00005-00203_00002" : { + "minimal_similarity" : 0.06040268456375839, + "maximum_similarity" : 0.06206896551724138, + "matched_token_number" : 9 + }, + "00014_00001-00119_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 150 + }, + "00000_00003-00092_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00130_00002-00133_00001" : { + "minimal_similarity" : 0.3630952380952381, + "maximum_similarity" : 0.45864661654135336, + "matched_token_number" : 61 + }, + "00097_00002-00140_00001" : { + "minimal_similarity" : 0.25675675675675674, + "maximum_similarity" : 0.2857142857142857, + "matched_token_number" : 38 + }, + "00014_00001-00126_00002" : { + "minimal_similarity" : 0.31333333333333335, + "maximum_similarity" : 0.32413793103448274, + "matched_token_number" : 47 + }, + "00138_00001-00197_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00113_00002-00184_00002" : { + "minimal_similarity" : 0.15568862275449102, + "maximum_similarity" : 0.2765957446808511, + "matched_token_number" : 26 + }, + "00031_00003-00092_00001" : { + "minimal_similarity" : 0.06944444444444445, + "maximum_similarity" : 0.08771929824561403, + "matched_token_number" : 10 + }, + "00113_00002-00184_00003" : { + "minimal_similarity" : 0.15568862275449102, + "maximum_similarity" : 0.2765957446808511, + "matched_token_number" : 26 + }, + "00126_00002-00194_00001" : { + "minimal_similarity" : 0.31333333333333335, + "maximum_similarity" : 0.32413793103448274, + "matched_token_number" : 47 + }, + "00125_00001-00187_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.17424242424242425, + "matched_token_number" : 23 + }, + "00092_00001-00121_00001" : { + "minimal_similarity" : 0.07772020725388601, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00127_00002-00204_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.19166666666666668, + "matched_token_number" : 23 + }, + "00000_00005-00013_00002" : { + "minimal_similarity" : 0.06040268456375839, + "maximum_similarity" : 0.06766917293233082, + "matched_token_number" : 9 + }, + "00131_00005-00199_00001" : { + "minimal_similarity" : 0.047619047619047616, + "maximum_similarity" : 0.09473684210526316, + "matched_token_number" : 9 + }, + "00126_00002-00134_00001" : { + "minimal_similarity" : 0.1724137931034483, + "maximum_similarity" : 0.21367521367521367, + "matched_token_number" : 25 + }, + "00140_00001-00197_00001" : { + "minimal_similarity" : 0.09774436090225563, + "maximum_similarity" : 0.09848484848484848, + "matched_token_number" : 13 + }, + "00000_00001-00013_00002" : { + "minimal_similarity" : 0.06766917293233082, + "maximum_similarity" : 0.07086614173228346, + "matched_token_number" : 9 + }, + "00135_00001-00178_00002" : { + "minimal_similarity" : 0.1956521739130435, + "maximum_similarity" : 0.21428571428571427, + "matched_token_number" : 36 + }, + "00186_00002-00198_00001" : { + "minimal_similarity" : 0.08080808080808081, + "maximum_similarity" : 0.09090909090909091, + "matched_token_number" : 16 + }, + "00201_00001-00202_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00154_00002-00204_00001" : { + "minimal_similarity" : 0.1402439024390244, + "maximum_similarity" : 0.19166666666666668, + "matched_token_number" : 23 + }, + "00131_00005-00204_00001" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.16666666666666666, + "matched_token_number" : 20 + }, + "00119_00001-00142_00001" : { + "minimal_similarity" : 0.30718954248366015, + "maximum_similarity" : 0.31333333333333335, + "matched_token_number" : 47 + }, + "00120_00001-00155_00001" : { + "minimal_similarity" : 0.2482758620689655, + "maximum_similarity" : 0.288, + "matched_token_number" : 36 + }, + "00199_00001-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00097_00002-00199_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00192_00001-00192_00002" : { + "minimal_similarity" : 0.6451612903225806, + "maximum_similarity" : 0.7633587786259542, + "matched_token_number" : 100 + }, + "00111_00001-00184_00002" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.2765957446808511, + "matched_token_number" : 26 + }, + "00111_00001-00184_00003" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.2765957446808511, + "matched_token_number" : 26 + }, + "00133_00001-00153_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00186_00002-00186_00004" : { + "minimal_similarity" : 0.3522727272727273, + "maximum_similarity" : 0.4305555555555556, + "matched_token_number" : 62 + }, + "00127_00002-00187_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.17424242424242425, + "matched_token_number" : 23 + }, + "00138_00001-00202_00003" : { + "minimal_similarity" : 0.08333333333333333, + "maximum_similarity" : 0.0851063829787234, + "matched_token_number" : 12 + }, + "00014_00001-00186_00002" : { + "minimal_similarity" : 0.1534090909090909, + "maximum_similarity" : 0.18, + "matched_token_number" : 27 + }, + "00138_00001-00202_00002" : { + "minimal_similarity" : 0.08333333333333333, + "maximum_similarity" : 0.0851063829787234, + "matched_token_number" : 12 + }, + "00156_00003-00204_00001" : { + "minimal_similarity" : 0.05056179775280899, + "maximum_similarity" : 0.075, + "matched_token_number" : 9 + }, + "00192_00001-00202_00002" : { + "minimal_similarity" : 0.6, + "maximum_similarity" : 0.6595744680851063, + "matched_token_number" : 93 + }, + "00192_00001-00202_00003" : { + "minimal_similarity" : 0.6451612903225806, + "maximum_similarity" : 0.7092198581560284, + "matched_token_number" : 100 + }, + "00014_00001-00186_00004" : { + "minimal_similarity" : 0.17333333333333334, + "maximum_similarity" : 0.18055555555555555, + "matched_token_number" : 26 + }, + "00178_00002-00187_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.17424242424242425, + "matched_token_number" : 23 + }, + "00133_00001-00203_00002" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.15862068965517243, + "matched_token_number" : 23 + }, + "00125_00001-00154_00002" : { + "minimal_similarity" : 0.8809523809523809, + "maximum_similarity" : 0.9024390243902439, + "matched_token_number" : 148 + }, + "00142_00001-00184_00002" : { + "minimal_similarity" : 0.1111111111111111, + "maximum_similarity" : 0.18085106382978725, + "matched_token_number" : 17 + }, + "00142_00001-00184_00003" : { + "minimal_similarity" : 0.1111111111111111, + "maximum_similarity" : 0.18085106382978725, + "matched_token_number" : 17 + }, + "00131_00005-00140_00001" : { + "minimal_similarity" : 0.06349206349206349, + "maximum_similarity" : 0.09022556390977443, + "matched_token_number" : 12 + }, + "00125_00001-00204_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.19166666666666668, + "matched_token_number" : 23 + }, + "00111_00001-00145_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00138_00001-00192_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00001-00130_00002" : { + "minimal_similarity" : 0.12030075187969924, + "maximum_similarity" : 0.12598425196850394, + "matched_token_number" : 16 + }, + "00119_00001-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00092_00001-00126_00002" : { + "minimal_similarity" : 0.12413793103448276, + "maximum_similarity" : 0.125, + "matched_token_number" : 18 + }, + "00129_00008-00141_00002" : { + "minimal_similarity" : 0.10638297872340426, + "maximum_similarity" : 0.2, + "matched_token_number" : 30 + }, + "00138_00001-00192_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00141_00002-00156_00003" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.07333333333333333, + "matched_token_number" : 11 + }, + "00000_00002-00005_00002" : { + "minimal_similarity" : 0.047619047619047616, + "maximum_similarity" : 0.0625, + "matched_token_number" : 9 + }, + "00031_00003-00135_00001" : { + "minimal_similarity" : 0.15760869565217392, + "maximum_similarity" : 0.2543859649122807, + "matched_token_number" : 29 + }, + "00014_00001-00203_00002" : { + "minimal_similarity" : 0.15333333333333332, + "maximum_similarity" : 0.15862068965517243, + "matched_token_number" : 23 + }, + "00141_00002-00156_00002" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.07333333333333333, + "matched_token_number" : 11 + }, + "00111_00001-00129_00008" : { + "minimal_similarity" : 0.10638297872340426, + "maximum_similarity" : 0.17857142857142858, + "matched_token_number" : 30 + }, + "00126_00002-00127_00002" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.2482758620689655, + "matched_token_number" : 36 + }, + "00005_00002-00147_00001" : { + "minimal_similarity" : 0.09523809523809523, + "maximum_similarity" : 0.125, + "matched_token_number" : 18 + }, + "00201_00001-00202_00003" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00005_00002-00044_00002" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.13970588235294118, + "matched_token_number" : 19 + }, + "00113_00002-00129_00008" : { + "minimal_similarity" : 0.10638297872340426, + "maximum_similarity" : 0.17964071856287425, + "matched_token_number" : 30 + }, + "00097_00002-00194_00001" : { + "minimal_similarity" : 0.18666666666666668, + "maximum_similarity" : 0.1891891891891892, + "matched_token_number" : 28 + }, + "00000_00002-00131_00005" : { + "minimal_similarity" : 0.047619047619047616, + "maximum_similarity" : 0.0625, + "matched_token_number" : 9 + }, + "00127_00002-00154_00002" : { + "minimal_similarity" : 0.8809523809523809, + "maximum_similarity" : 0.9024390243902439, + "matched_token_number" : 148 + }, + "00192_00002-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00119_00001-00154_00002" : { + "minimal_similarity" : 0.2682926829268293, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00186_00002-00203_00002" : { + "minimal_similarity" : 0.2215909090909091, + "maximum_similarity" : 0.2689655172413793, + "matched_token_number" : 39 + }, + "00000_00005-00177_00003" : { + "minimal_similarity" : 0.06547619047619048, + "maximum_similarity" : 0.0738255033557047, + "matched_token_number" : 11 + }, + "00131_00005-00145_00001" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00119_00001-00201_00001" : { + "minimal_similarity" : 0.24, + "maximum_similarity" : 0.27692307692307694, + "matched_token_number" : 36 + }, + "00000_00005-00130_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00001-00177_00003" : { + "minimal_similarity" : 0.1488095238095238, + "maximum_similarity" : 0.1968503937007874, + "matched_token_number" : 25 + }, + "00192_00002-00193_00001" : { + "minimal_similarity" : 0.12727272727272726, + "maximum_similarity" : 0.16030534351145037, + "matched_token_number" : 21 + }, + "00113_00002-00138_00001" : { + "minimal_similarity" : 0.08982035928143713, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00145_00001-00202_00002" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00183_00004-00192_00001" : { + "minimal_similarity" : 0.07741935483870968, + "maximum_similarity" : 0.08163265306122448, + "matched_token_number" : 12 + }, + "00000_00001-00135_00001" : { + "minimal_similarity" : 0.15760869565217392, + "maximum_similarity" : 0.2283464566929134, + "matched_token_number" : 29 + }, + "00145_00001-00202_00003" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00183_00004-00192_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00044_00002-00197_00001" : { + "minimal_similarity" : 0.40441176470588236, + "maximum_similarity" : 0.4166666666666667, + "matched_token_number" : 55 + }, + "00141_00002-00198_00001" : { + "minimal_similarity" : 0.10606060606060606, + "maximum_similarity" : 0.14, + "matched_token_number" : 21 + }, + "00111_00001-00140_00001" : { + "minimal_similarity" : 0.3630952380952381, + "maximum_similarity" : 0.45864661654135336, + "matched_token_number" : 61 + }, + "00111_00001-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00014_00001-00142_00001" : { + "minimal_similarity" : 0.30718954248366015, + "maximum_similarity" : 0.31333333333333335, + "matched_token_number" : 47 + }, + "00125_00001-00138_00001" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00005_00002-00154_00002" : { + "minimal_similarity" : 0.1111111111111111, + "maximum_similarity" : 0.12804878048780488, + "matched_token_number" : 21 + }, + "00183_00004-00195_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00111_00001-00201_00001" : { + "minimal_similarity" : 0.05357142857142857, + "maximum_similarity" : 0.06923076923076923, + "matched_token_number" : 9 + }, + "00183_00004-00200_00002" : { + "minimal_similarity" : 0.13529411764705881, + "maximum_similarity" : 0.1564625850340136, + "matched_token_number" : 23 + }, + "00183_00004-00195_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00131_00005-00187_00001" : { + "minimal_similarity" : 0.05291005291005291, + "maximum_similarity" : 0.07575757575757576, + "matched_token_number" : 10 + }, + "00014_00001-00135_00001" : { + "minimal_similarity" : 0.1956521739130435, + "maximum_similarity" : 0.24, + "matched_token_number" : 36 + }, + "00140_00001-00155_00001" : { + "minimal_similarity" : 0.39097744360902253, + "maximum_similarity" : 0.416, + "matched_token_number" : 52 + }, + "00113_00002-00142_00001" : { + "minimal_similarity" : 0.2155688622754491, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00127_00002-00138_00001" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00113_00002-00145_00001" : { + "minimal_similarity" : 0.9940476190476191, + "maximum_similarity" : 1.0, + "matched_token_number" : 167 + }, + "00000_00003-00097_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00129_00008-00192_00002" : { + "minimal_similarity" : 0.0851063829787234, + "maximum_similarity" : 0.183206106870229, + "matched_token_number" : 24 + }, + "00129_00008-00192_00001" : { + "minimal_similarity" : 0.11702127659574468, + "maximum_similarity" : 0.2129032258064516, + "matched_token_number" : 33 + }, + "00141_00002-00160_00001" : { + "minimal_similarity" : 0.08, + "maximum_similarity" : 0.08823529411764706, + "matched_token_number" : 12 + }, + "00145_00001-00194_00001" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00000_00005-00135_00001" : { + "minimal_similarity" : 0.10869565217391304, + "maximum_similarity" : 0.1342281879194631, + "matched_token_number" : 20 + }, + "00031_00003-00195_00001" : { + "minimal_similarity" : 0.0915032679738562, + "maximum_similarity" : 0.12280701754385964, + "matched_token_number" : 14 + }, + "00153_00001-00156_00002" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00031_00003-00195_00002" : { + "minimal_similarity" : 0.0915032679738562, + "maximum_similarity" : 0.12280701754385964, + "matched_token_number" : 14 + }, + "00113_00002-00201_00001" : { + "minimal_similarity" : 0.05389221556886228, + "maximum_similarity" : 0.06923076923076923, + "matched_token_number" : 9 + }, + "00153_00001-00156_00003" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00113_00002-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00097_00002-00145_00001" : { + "minimal_similarity" : 0.07738095238095238, + "maximum_similarity" : 0.08783783783783784, + "matched_token_number" : 13 + }, + "00013_00002-00120_00001" : { + "minimal_similarity" : 0.06896551724137931, + "maximum_similarity" : 0.07518796992481203, + "matched_token_number" : 10 + }, + "00000_00005-00186_00004" : { + "minimal_similarity" : 0.18791946308724833, + "maximum_similarity" : 0.19444444444444445, + "matched_token_number" : 28 + }, + "00111_00001-00138_00001" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00127_00002-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00001-00186_00002" : { + "minimal_similarity" : 0.2556818181818182, + "maximum_similarity" : 0.3543307086614173, + "matched_token_number" : 45 + }, + "00000_00005-00186_00002" : { + "minimal_similarity" : 0.17613636363636365, + "maximum_similarity" : 0.2080536912751678, + "matched_token_number" : 31 + }, + "00125_00001-00145_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00000_00001-00186_00004" : { + "minimal_similarity" : 0.2916666666666667, + "maximum_similarity" : 0.33070866141732286, + "matched_token_number" : 42 + }, + "00147_00001-00156_00003" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.0763888888888889, + "matched_token_number" : 11 + }, + "00147_00001-00156_00002" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.0763888888888889, + "matched_token_number" : 11 + }, + "00119_00001-00147_00001" : { + "minimal_similarity" : 0.1, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00000_00003-00156_00002" : { + "minimal_similarity" : 0.05056179775280899, + "maximum_similarity" : 0.060810810810810814, + "matched_token_number" : 9 + }, + "00131_00005-00194_00001" : { + "minimal_similarity" : 0.1111111111111111, + "maximum_similarity" : 0.14, + "matched_token_number" : 21 + }, + "00000_00003-00156_00003" : { + "minimal_similarity" : 0.05056179775280899, + "maximum_similarity" : 0.060810810810810814, + "matched_token_number" : 9 + }, + "00198_00001-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00186_00002-00193_00001" : { + "minimal_similarity" : 0.29545454545454547, + "maximum_similarity" : 0.3151515151515151, + "matched_token_number" : 52 + }, + "00133_00001-00160_00001" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.16176470588235295, + "matched_token_number" : 22 + }, + "00153_00001-00160_00001" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.16176470588235295, + "matched_token_number" : 22 + }, + "00125_00001-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00044_00002-00153_00001" : { + "minimal_similarity" : 0.16071428571428573, + "maximum_similarity" : 0.19852941176470587, + "matched_token_number" : 27 + }, + "00014_00001-00193_00001" : { + "minimal_similarity" : 0.07272727272727272, + "maximum_similarity" : 0.08, + "matched_token_number" : 12 + }, + "00111_00001-00142_00001" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00192_00001-00197_00001" : { + "minimal_similarity" : 0.5806451612903226, + "maximum_similarity" : 0.6818181818181818, + "matched_token_number" : 90 + }, + "00077_00001-00111_00001" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00097_00002-00204_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00127_00002-00145_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00153_00001-00184_00002" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.2765957446808511, + "matched_token_number" : 26 + }, + "00153_00001-00184_00003" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.2765957446808511, + "matched_token_number" : 26 + }, + "00134_00001-00200_00002" : { + "minimal_similarity" : 0.08823529411764706, + "maximum_similarity" : 0.1282051282051282, + "matched_token_number" : 15 + }, + "00184_00003-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00113_00002-00121_00001" : { + "minimal_similarity" : 0.6994818652849741, + "maximum_similarity" : 0.8083832335329342, + "matched_token_number" : 135 + }, + "00131_00005-00196_00001" : { + "minimal_similarity" : 0.024793388429752067, + "maximum_similarity" : 0.047619047619047616, + "matched_token_number" : 9 + }, + "00119_00001-00145_00001" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00121_00001-00138_00001" : { + "minimal_similarity" : 0.07772020725388601, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00031_00003-00193_00001" : { + "minimal_similarity" : 0.11515151515151516, + "maximum_similarity" : 0.16666666666666666, + "matched_token_number" : 19 + }, + "00126_00002-00197_00001" : { + "minimal_similarity" : 0.0896551724137931, + "maximum_similarity" : 0.09848484848484848, + "matched_token_number" : 13 + }, + "00005_00002-00014_00001" : { + "minimal_similarity" : 0.1111111111111111, + "maximum_similarity" : 0.14, + "matched_token_number" : 21 + }, + "00000_00005-00121_00001" : { + "minimal_similarity" : 0.05699481865284974, + "maximum_similarity" : 0.0738255033557047, + "matched_token_number" : 11 + }, + "00160_00001-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00127_00002-00131_00005" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00031_00002-00113_00002" : { + "minimal_similarity" : 0.0658682634730539, + "maximum_similarity" : 0.08870967741935484, + "matched_token_number" : 11 + }, + "00000_00005-00126_00002" : { + "minimal_similarity" : 0.06711409395973154, + "maximum_similarity" : 0.06896551724137931, + "matched_token_number" : 10 + }, + "00127_00002-00184_00003" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.2765957446808511, + "matched_token_number" : 26 + }, + "00000_00003-00121_00001" : { + "minimal_similarity" : 0.10362694300518134, + "maximum_similarity" : 0.13513513513513514, + "matched_token_number" : 20 + }, + "00127_00002-00184_00002" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.2765957446808511, + "matched_token_number" : 26 + }, + "00133_00001-00200_00002" : { + "minimal_similarity" : 0.06470588235294118, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00031_00003-00153_00001" : { + "minimal_similarity" : 0.14285714285714285, + "maximum_similarity" : 0.21052631578947367, + "matched_token_number" : 24 + }, + "00000_00002-00187_00001" : { + "minimal_similarity" : 0.20833333333333334, + "maximum_similarity" : 0.22727272727272727, + "matched_token_number" : 30 + }, + "00199_00001-00203_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00013_00002-00197_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00111_00001-00187_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.17424242424242425, + "matched_token_number" : 23 + }, + "00005_00002-00140_00001" : { + "minimal_similarity" : 0.06349206349206349, + "maximum_similarity" : 0.09022556390977443, + "matched_token_number" : 12 + }, + "00177_00003-00198_00001" : { + "minimal_similarity" : 0.18686868686868688, + "maximum_similarity" : 0.22023809523809523, + "matched_token_number" : 37 + }, + "00126_00002-00131_00005" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.13793103448275862, + "matched_token_number" : 20 + }, + "00005_00002-00198_00001" : { + "minimal_similarity" : 0.050505050505050504, + "maximum_similarity" : 0.05291005291005291, + "matched_token_number" : 10 + }, + "00111_00001-00147_00001" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00000_00001-00147_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00003-00147_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00145_00001-00204_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.19166666666666668, + "matched_token_number" : 23 + }, + "00119_00001-00193_00001" : { + "minimal_similarity" : 0.07272727272727272, + "maximum_similarity" : 0.08, + "matched_token_number" : 12 + }, + "00156_00003-00184_00003" : { + "minimal_similarity" : 0.06741573033707865, + "maximum_similarity" : 0.1276595744680851, + "matched_token_number" : 12 + }, + "00000_00003-00193_00001" : { + "minimal_similarity" : 0.06666666666666667, + "maximum_similarity" : 0.07432432432432433, + "matched_token_number" : 11 + }, + "00183_00004-00197_00001" : { + "minimal_similarity" : 0.07482993197278912, + "maximum_similarity" : 0.08333333333333333, + "matched_token_number" : 11 + }, + "00156_00003-00184_00002" : { + "minimal_similarity" : 0.06741573033707865, + "maximum_similarity" : 0.1276595744680851, + "matched_token_number" : 12 + }, + "00147_00001-00153_00001" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00000_00005-00153_00001" : { + "minimal_similarity" : 0.06547619047619048, + "maximum_similarity" : 0.0738255033557047, + "matched_token_number" : 11 + }, + "00154_00002-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00142_00001-00193_00001" : { + "minimal_similarity" : 0.12727272727272726, + "maximum_similarity" : 0.13725490196078433, + "matched_token_number" : 21 + }, + "00044_00002-00155_00001" : { + "minimal_similarity" : 0.19852941176470587, + "maximum_similarity" : 0.216, + "matched_token_number" : 27 + }, + "00077_00001-00155_00001" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.152, + "matched_token_number" : 19 + }, + "00156_00002-00197_00001" : { + "minimal_similarity" : 0.05056179775280899, + "maximum_similarity" : 0.06818181818181818, + "matched_token_number" : 9 + }, + "00121_00001-00133_00001" : { + "minimal_similarity" : 0.7046632124352331, + "maximum_similarity" : 0.8095238095238095, + "matched_token_number" : 136 + }, + "00044_00002-00195_00002" : { + "minimal_similarity" : 0.10457516339869281, + "maximum_similarity" : 0.11764705882352941, + "matched_token_number" : 16 + }, + "00044_00002-00195_00001" : { + "minimal_similarity" : 0.10457516339869281, + "maximum_similarity" : 0.11764705882352941, + "matched_token_number" : 16 + }, + "00000_00001-00193_00001" : { + "minimal_similarity" : 0.12727272727272726, + "maximum_similarity" : 0.16535433070866143, + "matched_token_number" : 21 + }, + "00005_00002-00177_00003" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00119_00001-00177_00003" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00130_00002-00177_00003" : { + "minimal_similarity" : 0.3630952380952381, + "maximum_similarity" : 0.45864661654135336, + "matched_token_number" : 61 + }, + "00000_00003-00126_00002" : { + "minimal_similarity" : 0.12837837837837837, + "maximum_similarity" : 0.1310344827586207, + "matched_token_number" : 19 + }, + "00184_00003-00195_00001" : { + "minimal_similarity" : 0.1111111111111111, + "maximum_similarity" : 0.18085106382978725, + "matched_token_number" : 17 + }, + "00127_00002-00136_00002" : { + "minimal_similarity" : 0.0867579908675799, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00195_00002-00199_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00137_00002-00154_00002" : { + "minimal_similarity" : 0.8809523809523809, + "maximum_similarity" : 0.9024390243902439, + "matched_token_number" : 148 + }, + "00184_00003-00195_00002" : { + "minimal_similarity" : 0.1111111111111111, + "maximum_similarity" : 0.18085106382978725, + "matched_token_number" : 17 + }, + "00113_00002-00140_00001" : { + "minimal_similarity" : 0.3652694610778443, + "maximum_similarity" : 0.45864661654135336, + "matched_token_number" : 61 + }, + "00111_00001-00204_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.19166666666666668, + "matched_token_number" : 23 + }, + "00000_00003-00142_00001" : { + "minimal_similarity" : 0.12418300653594772, + "maximum_similarity" : 0.12837837837837837, + "matched_token_number" : 19 + }, + "00000_00001-00142_00001" : { + "minimal_similarity" : 0.16339869281045752, + "maximum_similarity" : 0.1968503937007874, + "matched_token_number" : 25 + }, + "00177_00003-00193_00001" : { + "minimal_similarity" : 0.07142857142857142, + "maximum_similarity" : 0.07272727272727272, + "matched_token_number" : 12 + }, + "00119_00001-00126_00002" : { + "minimal_similarity" : 0.31333333333333335, + "maximum_similarity" : 0.32413793103448274, + "matched_token_number" : 47 + }, + "00031_00002-00134_00001" : { + "minimal_similarity" : 0.18548387096774194, + "maximum_similarity" : 0.19658119658119658, + "matched_token_number" : 23 + }, + "00013_00002-00192_00001" : { + "minimal_similarity" : 0.05806451612903226, + "maximum_similarity" : 0.06766917293233082, + "matched_token_number" : 9 + }, + "00013_00002-00192_00002" : { + "minimal_similarity" : 0.06766917293233082, + "maximum_similarity" : 0.06870229007633588, + "matched_token_number" : 9 + }, + "00005_00002-00193_00001" : { + "minimal_similarity" : 0.12169312169312169, + "maximum_similarity" : 0.1393939393939394, + "matched_token_number" : 23 + }, + "00000_00002-00155_00001" : { + "minimal_similarity" : 0.0625, + "maximum_similarity" : 0.072, + "matched_token_number" : 9 + }, + "00031_00003-00177_00003" : { + "minimal_similarity" : 0.14285714285714285, + "maximum_similarity" : 0.21052631578947367, + "matched_token_number" : 24 + }, + "00145_00001-00187_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.17424242424242425, + "matched_token_number" : 23 + }, + "00013_00002-00125_00001" : { + "minimal_similarity" : 0.18452380952380953, + "maximum_similarity" : 0.23308270676691728, + "matched_token_number" : 31 + }, + "00000_00003-00198_00001" : { + "minimal_similarity" : 0.10101010101010101, + "maximum_similarity" : 0.13513513513513514, + "matched_token_number" : 20 + }, + "00005_00002-00121_00001" : { + "minimal_similarity" : 0.09844559585492228, + "maximum_similarity" : 0.10052910052910052, + "matched_token_number" : 19 + }, + "00177_00003-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00133_00001-00141_00002" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00000_00001-00195_00002" : { + "minimal_similarity" : 0.16339869281045752, + "maximum_similarity" : 0.1968503937007874, + "matched_token_number" : 25 + }, + "00000_00001-00195_00001" : { + "minimal_similarity" : 0.16339869281045752, + "maximum_similarity" : 0.1968503937007874, + "matched_token_number" : 25 + }, + "00031_00002-00187_00001" : { + "minimal_similarity" : 0.13636363636363635, + "maximum_similarity" : 0.14516129032258066, + "matched_token_number" : 18 + }, + "00121_00001-00131_00005" : { + "minimal_similarity" : 0.09844559585492228, + "maximum_similarity" : 0.10052910052910052, + "matched_token_number" : 19 + }, + "00000_00001-00198_00001" : { + "minimal_similarity" : 0.05555555555555555, + "maximum_similarity" : 0.08661417322834646, + "matched_token_number" : 11 + }, + "00177_00003-00204_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.19166666666666668, + "matched_token_number" : 23 + }, + "00125_00001-00178_00002" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00005_00002-00204_00001" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.16666666666666666, + "matched_token_number" : 20 + }, + "00140_00001-00195_00002" : { + "minimal_similarity" : 0.17647058823529413, + "maximum_similarity" : 0.20300751879699247, + "matched_token_number" : 27 + }, + "00077_00001-00153_00001" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00140_00001-00195_00001" : { + "minimal_similarity" : 0.17647058823529413, + "maximum_similarity" : 0.20300751879699247, + "matched_token_number" : 27 + }, + "00121_00001-00184_00003" : { + "minimal_similarity" : 0.11917098445595854, + "maximum_similarity" : 0.24468085106382978, + "matched_token_number" : 23 + }, + "00121_00001-00184_00002" : { + "minimal_similarity" : 0.11917098445595854, + "maximum_similarity" : 0.24468085106382978, + "matched_token_number" : 23 + }, + "00119_00001-00156_00003" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.07333333333333333, + "matched_token_number" : 11 + }, + "00092_00001-00156_00002" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.0763888888888889, + "matched_token_number" : 11 + }, + "00092_00001-00156_00003" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.0763888888888889, + "matched_token_number" : 11 + }, + "00000_00003-00195_00002" : { + "minimal_similarity" : 0.12418300653594772, + "maximum_similarity" : 0.12837837837837837, + "matched_token_number" : 19 + }, + "00136_00002-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00003-00195_00001" : { + "minimal_similarity" : 0.12418300653594772, + "maximum_similarity" : 0.12837837837837837, + "matched_token_number" : 19 + }, + "00119_00001-00156_00002" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.07333333333333333, + "matched_token_number" : 11 + }, + "00138_00001-00199_00001" : { + "minimal_similarity" : 0.06944444444444445, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 10 + }, + "00000_00002-00077_00001" : { + "minimal_similarity" : 0.047619047619047616, + "maximum_similarity" : 0.0625, + "matched_token_number" : 9 + }, + "00005_00002-00196_00001" : { + "minimal_similarity" : 0.024793388429752067, + "maximum_similarity" : 0.047619047619047616, + "matched_token_number" : 9 + }, + "00013_00002-00160_00001" : { + "minimal_similarity" : 0.0661764705882353, + "maximum_similarity" : 0.06766917293233082, + "matched_token_number" : 9 + }, + "00044_00002-00192_00001" : { + "minimal_similarity" : 0.3419354838709677, + "maximum_similarity" : 0.3897058823529412, + "matched_token_number" : 53 + }, + "00044_00002-00192_00002" : { + "minimal_similarity" : 0.38235294117647056, + "maximum_similarity" : 0.3969465648854962, + "matched_token_number" : 52 + }, + "00126_00002-00199_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00127_00002-00133_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00195_00002-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00156_00003-00187_00001" : { + "minimal_similarity" : 0.05056179775280899, + "maximum_similarity" : 0.06818181818181818, + "matched_token_number" : 9 + }, + "00014_00001-00095_00003" : { + "minimal_similarity" : 0.10891089108910891, + "maximum_similarity" : 0.14666666666666667, + "matched_token_number" : 22 + }, + "00111_00001-00131_00005" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00134_00001-00199_00001" : { + "minimal_similarity" : 0.10256410256410256, + "maximum_similarity" : 0.12631578947368421, + "matched_token_number" : 12 + }, + "00138_00001-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00092_00001-00135_00001" : { + "minimal_similarity" : 0.08152173913043478, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00000_00002-00134_00001" : { + "minimal_similarity" : 0.0625, + "maximum_similarity" : 0.07692307692307693, + "matched_token_number" : 9 + }, + "00119_00001-00129_00008" : { + "minimal_similarity" : 0.10638297872340426, + "maximum_similarity" : 0.2, + "matched_token_number" : 30 + }, + "00121_00001-00154_00002" : { + "minimal_similarity" : 0.616580310880829, + "maximum_similarity" : 0.725609756097561, + "matched_token_number" : 119 + }, + "00184_00002-00187_00001" : { + "minimal_similarity" : 0.10606060606060606, + "maximum_similarity" : 0.14893617021276595, + "matched_token_number" : 14 + }, + "00202_00002-00203_00002" : { + "minimal_similarity" : 0.2896551724137931, + "maximum_similarity" : 0.2978723404255319, + "matched_token_number" : 42 + }, + "00119_00001-00140_00001" : { + "minimal_similarity" : 0.32666666666666666, + "maximum_similarity" : 0.3684210526315789, + "matched_token_number" : 49 + }, + "00031_00003-00126_00002" : { + "minimal_similarity" : 0.09655172413793103, + "maximum_similarity" : 0.12280701754385964, + "matched_token_number" : 14 + }, + "00005_00002-00145_00001" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00113_00002-00126_00002" : { + "minimal_similarity" : 0.2155688622754491, + "maximum_similarity" : 0.2482758620689655, + "matched_token_number" : 36 + }, + "00092_00001-00154_00002" : { + "minimal_similarity" : 0.07926829268292683, + "maximum_similarity" : 0.09027777777777778, + "matched_token_number" : 13 + }, + "00077_00001-00137_00002" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00200_00002-00202_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00130_00002-00204_00001" : { + "minimal_similarity" : 0.09774436090225563, + "maximum_similarity" : 0.10833333333333334, + "matched_token_number" : 13 + }, + "00134_00001-00178_00002" : { + "minimal_similarity" : 0.1488095238095238, + "maximum_similarity" : 0.21367521367521367, + "matched_token_number" : 25 + }, + "00044_00002-00120_00001" : { + "minimal_similarity" : 0.1103448275862069, + "maximum_similarity" : 0.11764705882352941, + "matched_token_number" : 16 + }, + "00141_00002-00184_00003" : { + "minimal_similarity" : 0.18, + "maximum_similarity" : 0.2872340425531915, + "matched_token_number" : 27 + }, + "00097_00002-00133_00001" : { + "minimal_similarity" : 0.07738095238095238, + "maximum_similarity" : 0.08783783783783784, + "matched_token_number" : 13 + }, + "00141_00002-00184_00002" : { + "minimal_similarity" : 0.18, + "maximum_similarity" : 0.2872340425531915, + "matched_token_number" : 27 + }, + "00140_00001-00202_00003" : { + "minimal_similarity" : 0.07092198581560284, + "maximum_similarity" : 0.07518796992481203, + "matched_token_number" : 10 + }, + "00013_00002-00141_00002" : { + "minimal_similarity" : 0.13333333333333333, + "maximum_similarity" : 0.15037593984962405, + "matched_token_number" : 20 + }, + "00000_00003-00013_00002" : { + "minimal_similarity" : 0.060810810810810814, + "maximum_similarity" : 0.06766917293233082, + "matched_token_number" : 9 + }, + "00135_00001-00145_00001" : { + "minimal_similarity" : 0.1956521739130435, + "maximum_similarity" : 0.21428571428571427, + "matched_token_number" : 36 + }, + "00097_00002-00113_00002" : { + "minimal_similarity" : 0.07784431137724551, + "maximum_similarity" : 0.08783783783783784, + "matched_token_number" : 13 + }, + "00140_00001-00202_00002" : { + "minimal_similarity" : 0.07092198581560284, + "maximum_similarity" : 0.07518796992481203, + "matched_token_number" : 10 + }, + "00092_00001-00187_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00113_00002-00177_00003" : { + "minimal_similarity" : 0.9940476190476191, + "maximum_similarity" : 1.0, + "matched_token_number" : 167 + }, + "00129_00008-00153_00001" : { + "minimal_similarity" : 0.10638297872340426, + "maximum_similarity" : 0.17857142857142858, + "matched_token_number" : 30 + }, + "00000_00002-00136_00002" : { + "minimal_similarity" : 0.0410958904109589, + "maximum_similarity" : 0.0625, + "matched_token_number" : 9 + }, + "00136_00002-00137_00002" : { + "minimal_similarity" : 0.0867579908675799, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00142_00001-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00130_00002-00140_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 133 + }, + "00195_00002-00201_00001" : { + "minimal_similarity" : 0.12418300653594772, + "maximum_similarity" : 0.14615384615384616, + "matched_token_number" : 19 + }, + "00130_00002-00160_00001" : { + "minimal_similarity" : 0.16911764705882354, + "maximum_similarity" : 0.17293233082706766, + "matched_token_number" : 23 + }, + "00031_00003-00156_00002" : { + "minimal_similarity" : 0.10674157303370786, + "maximum_similarity" : 0.16666666666666666, + "matched_token_number" : 19 + }, + "00031_00003-00156_00003" : { + "minimal_similarity" : 0.10674157303370786, + "maximum_similarity" : 0.16666666666666666, + "matched_token_number" : 19 + }, + "00160_00001-00186_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00184_00003-00193_00001" : { + "minimal_similarity" : 0.07272727272727272, + "maximum_similarity" : 0.1276595744680851, + "matched_token_number" : 12 + }, + "00031_00002-00136_00002" : { + "minimal_similarity" : 0.0821917808219178, + "maximum_similarity" : 0.14516129032258066, + "matched_token_number" : 18 + }, + "00160_00001-00186_00002" : { + "minimal_similarity" : 0.07386363636363637, + "maximum_similarity" : 0.09558823529411764, + "matched_token_number" : 13 + }, + "00133_00001-00193_00001" : { + "minimal_similarity" : 0.07142857142857142, + "maximum_similarity" : 0.07272727272727272, + "matched_token_number" : 12 + }, + "00120_00001-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00184_00003-00203_00002" : { + "minimal_similarity" : 0.09655172413793103, + "maximum_similarity" : 0.14893617021276595, + "matched_token_number" : 14 + }, + "00155_00001-00187_00001" : { + "minimal_similarity" : 0.12878787878787878, + "maximum_similarity" : 0.136, + "matched_token_number" : 17 + }, + "00095_00003-00187_00001" : { + "minimal_similarity" : 0.0594059405940594, + "maximum_similarity" : 0.09090909090909091, + "matched_token_number" : 12 + }, + "00031_00002-00077_00001" : { + "minimal_similarity" : 0.047619047619047616, + "maximum_similarity" : 0.07258064516129033, + "matched_token_number" : 9 + }, + "00140_00001-00192_00001" : { + "minimal_similarity" : 0.08387096774193549, + "maximum_similarity" : 0.09774436090225563, + "matched_token_number" : 13 + }, + "00140_00001-00192_00002" : { + "minimal_similarity" : 0.12030075187969924, + "maximum_similarity" : 0.12213740458015267, + "matched_token_number" : 16 + }, + "00092_00001-00097_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00156_00002-00203_00002" : { + "minimal_similarity" : 0.06741573033707865, + "maximum_similarity" : 0.08275862068965517, + "matched_token_number" : 12 + }, + "00095_00003-00154_00002" : { + "minimal_similarity" : 0.10891089108910891, + "maximum_similarity" : 0.13414634146341464, + "matched_token_number" : 22 + }, + "00147_00001-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00120_00001-00136_00002" : { + "minimal_similarity" : 0.0547945205479452, + "maximum_similarity" : 0.08275862068965517, + "matched_token_number" : 12 + }, + "00133_00001-00192_00002" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.1984732824427481, + "matched_token_number" : 26 + }, + "00133_00001-00192_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.14838709677419354, + "matched_token_number" : 23 + }, + "00130_00002-00147_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00003-00201_00001" : { + "minimal_similarity" : 0.060810810810810814, + "maximum_similarity" : 0.06923076923076923, + "matched_token_number" : 9 + }, + "00135_00001-00140_00001" : { + "minimal_similarity" : 0.20652173913043478, + "maximum_similarity" : 0.2857142857142857, + "matched_token_number" : 38 + }, + "00013_00002-00031_00003" : { + "minimal_similarity" : 0.16541353383458646, + "maximum_similarity" : 0.19298245614035087, + "matched_token_number" : 22 + }, + "00130_00002-00193_00001" : { + "minimal_similarity" : 0.07272727272727272, + "maximum_similarity" : 0.09022556390977443, + "matched_token_number" : 12 + }, + "00013_00002-00031_00002" : { + "minimal_similarity" : 0.07518796992481203, + "maximum_similarity" : 0.08064516129032258, + "matched_token_number" : 10 + }, + "00005_00002-00142_00001" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.13071895424836602, + "matched_token_number" : 20 + }, + "00142_00001-00201_00001" : { + "minimal_similarity" : 0.12418300653594772, + "maximum_similarity" : 0.14615384615384616, + "matched_token_number" : 19 + }, + "00134_00001-00202_00002" : { + "minimal_similarity" : 0.07801418439716312, + "maximum_similarity" : 0.09401709401709402, + "matched_token_number" : 11 + }, + "00134_00001-00202_00003" : { + "minimal_similarity" : 0.07801418439716312, + "maximum_similarity" : 0.09401709401709402, + "matched_token_number" : 11 + }, + "00153_00001-00186_00002" : { + "minimal_similarity" : 0.1534090909090909, + "maximum_similarity" : 0.16071428571428573, + "matched_token_number" : 27 + }, + "00000_00003-00177_00003" : { + "minimal_similarity" : 0.11904761904761904, + "maximum_similarity" : 0.13513513513513514, + "matched_token_number" : 20 + }, + "00153_00001-00186_00004" : { + "minimal_similarity" : 0.16666666666666666, + "maximum_similarity" : 0.19444444444444445, + "matched_token_number" : 28 + }, + "00135_00001-00199_00001" : { + "minimal_similarity" : 0.05434782608695652, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 10 + }, + "00014_00001-00121_00001" : { + "minimal_similarity" : 0.27461139896373055, + "maximum_similarity" : 0.35333333333333333, + "matched_token_number" : 53 + }, + "00154_00002-00178_00002" : { + "minimal_similarity" : 0.8809523809523809, + "maximum_similarity" : 0.9024390243902439, + "matched_token_number" : 148 + }, + "00135_00001-00204_00001" : { + "minimal_similarity" : 0.05434782608695652, + "maximum_similarity" : 0.08333333333333333, + "matched_token_number" : 10 + }, + "00013_00002-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00013_00002-00195_00002" : { + "minimal_similarity" : 0.06535947712418301, + "maximum_similarity" : 0.07518796992481203, + "matched_token_number" : 10 + }, + "00000_00003-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00013_00002-00195_00001" : { + "minimal_similarity" : 0.06535947712418301, + "maximum_similarity" : 0.07518796992481203, + "matched_token_number" : 10 + }, + "00120_00001-00131_00005" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.13793103448275862, + "matched_token_number" : 20 + }, + "00142_00001-00145_00001" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00120_00001-00134_00001" : { + "minimal_similarity" : 0.1724137931034483, + "maximum_similarity" : 0.21367521367521367, + "matched_token_number" : 25 + }, + "00077_00001-00183_00004" : { + "minimal_similarity" : 0.09523809523809523, + "maximum_similarity" : 0.12244897959183673, + "matched_token_number" : 18 + }, + "00120_00001-00187_00001" : { + "minimal_similarity" : 0.0896551724137931, + "maximum_similarity" : 0.09848484848484848, + "matched_token_number" : 13 + }, + "00142_00001-00198_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00130_00002-00142_00001" : { + "minimal_similarity" : 0.17647058823529413, + "maximum_similarity" : 0.20300751879699247, + "matched_token_number" : 27 + }, + "00133_00001-00177_00003" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00134_00001-00141_00002" : { + "minimal_similarity" : 0.26, + "maximum_similarity" : 0.3333333333333333, + "matched_token_number" : 39 + }, + "00156_00002-00192_00002" : { + "minimal_similarity" : 0.05056179775280899, + "maximum_similarity" : 0.06870229007633588, + "matched_token_number" : 9 + }, + "00156_00002-00192_00001" : { + "minimal_similarity" : 0.05056179775280899, + "maximum_similarity" : 0.05806451612903226, + "matched_token_number" : 9 + }, + "00129_00008-00155_00001" : { + "minimal_similarity" : 0.1276595744680851, + "maximum_similarity" : 0.288, + "matched_token_number" : 36 + }, + "00000_00003-00031_00002" : { + "minimal_similarity" : 0.12837837837837837, + "maximum_similarity" : 0.1532258064516129, + "matched_token_number" : 19 + }, + "00000_00003-00031_00003" : { + "minimal_similarity" : 0.12837837837837837, + "maximum_similarity" : 0.16666666666666666, + "matched_token_number" : 19 + }, + "00147_00001-00184_00002" : { + "minimal_similarity" : 0.06944444444444445, + "maximum_similarity" : 0.10638297872340426, + "matched_token_number" : 10 + }, + "00147_00001-00184_00003" : { + "minimal_similarity" : 0.06944444444444445, + "maximum_similarity" : 0.10638297872340426, + "matched_token_number" : 10 + }, + "00156_00002-00195_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00134_00001-00194_00001" : { + "minimal_similarity" : 0.26, + "maximum_similarity" : 0.3333333333333333, + "matched_token_number" : 39 + }, + "00156_00002-00195_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00095_00003-00138_00001" : { + "minimal_similarity" : 0.054455445544554455, + "maximum_similarity" : 0.0763888888888889, + "matched_token_number" : 11 + }, + "00005_00002-00126_00002" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.13793103448275862, + "matched_token_number" : 20 + }, + "00013_00002-00203_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00200_00002-00201_00001" : { + "minimal_similarity" : 0.1588235294117647, + "maximum_similarity" : 0.2076923076923077, + "matched_token_number" : 27 + }, + "00005_00002-00129_00008" : { + "minimal_similarity" : 0.03546099290780142, + "maximum_similarity" : 0.05291005291005291, + "matched_token_number" : 10 + }, + "00135_00001-00194_00001" : { + "minimal_similarity" : 0.1956521739130435, + "maximum_similarity" : 0.24, + "matched_token_number" : 36 + }, + "00119_00001-00121_00001" : { + "minimal_similarity" : 0.27461139896373055, + "maximum_similarity" : 0.35333333333333333, + "matched_token_number" : 53 + }, + "00137_00002-00138_00001" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00135_00001-00201_00001" : { + "minimal_similarity" : 0.04891304347826087, + "maximum_similarity" : 0.06923076923076923, + "matched_token_number" : 9 + }, + "00092_00001-00095_00003" : { + "minimal_similarity" : 0.054455445544554455, + "maximum_similarity" : 0.0763888888888889, + "matched_token_number" : 11 + }, + "00000_00005-00097_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00031_00003-00121_00001" : { + "minimal_similarity" : 0.21243523316062177, + "maximum_similarity" : 0.35964912280701755, + "matched_token_number" : 41 + }, + "00130_00002-00198_00001" : { + "minimal_similarity" : 0.045454545454545456, + "maximum_similarity" : 0.06766917293233082, + "matched_token_number" : 9 + }, + "00121_00001-00187_00001" : { + "minimal_similarity" : 0.12953367875647667, + "maximum_similarity" : 0.1893939393939394, + "matched_token_number" : 25 + }, + "00013_00002-00202_00003" : { + "minimal_similarity" : 0.1347517730496454, + "maximum_similarity" : 0.14285714285714285, + "matched_token_number" : 19 + }, + "00135_00001-00202_00002" : { + "minimal_similarity" : 0.125, + "maximum_similarity" : 0.16312056737588654, + "matched_token_number" : 23 + }, + "00142_00001-00147_00001" : { + "minimal_similarity" : 0.11764705882352941, + "maximum_similarity" : 0.125, + "matched_token_number" : 18 + }, + "00141_00002-00183_00004" : { + "minimal_similarity" : 0.07333333333333333, + "maximum_similarity" : 0.07482993197278912, + "matched_token_number" : 11 + }, + "00147_00001-00186_00002" : { + "minimal_similarity" : 0.056818181818181816, + "maximum_similarity" : 0.06944444444444445, + "matched_token_number" : 10 + }, + "00147_00001-00186_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00005-00156_00002" : { + "minimal_similarity" : 0.05056179775280899, + "maximum_similarity" : 0.06040268456375839, + "matched_token_number" : 9 + }, + "00000_00005-00156_00003" : { + "minimal_similarity" : 0.05056179775280899, + "maximum_similarity" : 0.06040268456375839, + "matched_token_number" : 9 + }, + "00044_00002-00125_00001" : { + "minimal_similarity" : 0.16071428571428573, + "maximum_similarity" : 0.19852941176470587, + "matched_token_number" : 27 + }, + "00121_00001-00136_00002" : { + "minimal_similarity" : 0.1278538812785388, + "maximum_similarity" : 0.14507772020725387, + "matched_token_number" : 28 + }, + "00000_00001-00111_00001" : { + "minimal_similarity" : 0.1488095238095238, + "maximum_similarity" : 0.1968503937007874, + "matched_token_number" : 25 + }, + "00077_00001-00186_00002" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.11363636363636363, + "matched_token_number" : 20 + }, + "00134_00001-00192_00001" : { + "minimal_similarity" : 0.07096774193548387, + "maximum_similarity" : 0.09401709401709402, + "matched_token_number" : 11 + }, + "00134_00001-00192_00002" : { + "minimal_similarity" : 0.11450381679389313, + "maximum_similarity" : 0.1282051282051282, + "matched_token_number" : 15 + }, + "00156_00002-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00135_00001-00196_00001" : { + "minimal_similarity" : 0.06060606060606061, + "maximum_similarity" : 0.11956521739130435, + "matched_token_number" : 22 + }, + "00077_00001-00186_00004" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.1388888888888889, + "matched_token_number" : 20 + }, + "00130_00002-00145_00001" : { + "minimal_similarity" : 0.3630952380952381, + "maximum_similarity" : 0.45864661654135336, + "matched_token_number" : 61 + }, + "00135_00001-00202_00003" : { + "minimal_similarity" : 0.11413043478260869, + "maximum_similarity" : 0.14893617021276595, + "matched_token_number" : 21 + }, + "00031_00002-00131_00005" : { + "minimal_similarity" : 0.047619047619047616, + "maximum_similarity" : 0.07258064516129033, + "matched_token_number" : 9 + }, + "00130_00002-00203_00002" : { + "minimal_similarity" : 0.0896551724137931, + "maximum_similarity" : 0.09774436090225563, + "matched_token_number" : 13 + }, + "00130_00002-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00200_00002-00202_00003" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00013_00002-00202_00002" : { + "minimal_similarity" : 0.19858156028368795, + "maximum_similarity" : 0.21052631578947367, + "matched_token_number" : 28 + }, + "00077_00001-00134_00001" : { + "minimal_similarity" : 0.047619047619047616, + "maximum_similarity" : 0.07692307692307693, + "matched_token_number" : 9 + }, + "00142_00001-00204_00001" : { + "minimal_similarity" : 0.08496732026143791, + "maximum_similarity" : 0.10833333333333334, + "matched_token_number" : 13 + }, + "00119_00001-00178_00002" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00130_00002-00136_00002" : { + "minimal_similarity" : 0.0502283105022831, + "maximum_similarity" : 0.08270676691729323, + "matched_token_number" : 11 + }, + "00129_00008-00156_00003" : { + "minimal_similarity" : 0.03900709219858156, + "maximum_similarity" : 0.06179775280898876, + "matched_token_number" : 11 + }, + "00005_00002-00178_00002" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00129_00008-00156_00002" : { + "minimal_similarity" : 0.03900709219858156, + "maximum_similarity" : 0.06179775280898876, + "matched_token_number" : 11 + }, + "00113_00002-00194_00001" : { + "minimal_similarity" : 0.2634730538922156, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00119_00001-00203_00002" : { + "minimal_similarity" : 0.15333333333333332, + "maximum_similarity" : 0.15862068965517243, + "matched_token_number" : 23 + }, + "00044_00002-00092_00001" : { + "minimal_similarity" : 0.06944444444444445, + "maximum_similarity" : 0.07352941176470588, + "matched_token_number" : 10 + }, + "00184_00002-00196_00001" : { + "minimal_similarity" : 0.024793388429752067, + "maximum_similarity" : 0.09574468085106383, + "matched_token_number" : 9 + }, + "00137_00002-00147_00001" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00138_00001-00187_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00125_00001-00177_00003" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00196_00001-00204_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00131_00005-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00135_00001-00155_00001" : { + "minimal_similarity" : 0.1358695652173913, + "maximum_similarity" : 0.2, + "matched_token_number" : 25 + }, + "00000_00003-00141_00002" : { + "minimal_similarity" : 0.13333333333333333, + "maximum_similarity" : 0.13513513513513514, + "matched_token_number" : 20 + }, + "00031_00003-00120_00001" : { + "minimal_similarity" : 0.09655172413793103, + "maximum_similarity" : 0.12280701754385964, + "matched_token_number" : 14 + }, + "00120_00001-00140_00001" : { + "minimal_similarity" : 0.18620689655172415, + "maximum_similarity" : 0.20300751879699247, + "matched_token_number" : 27 + }, + "00014_00001-00183_00004" : { + "minimal_similarity" : 0.07333333333333333, + "maximum_similarity" : 0.07482993197278912, + "matched_token_number" : 11 + }, + "00147_00001-00192_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00031_00003-00133_00001" : { + "minimal_similarity" : 0.14285714285714285, + "maximum_similarity" : 0.21052631578947367, + "matched_token_number" : 24 + }, + "00147_00001-00192_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00154_00002-00177_00003" : { + "minimal_similarity" : 0.8809523809523809, + "maximum_similarity" : 0.9024390243902439, + "matched_token_number" : 148 + }, + "00000_00001-00141_00002" : { + "minimal_similarity" : 0.18, + "maximum_similarity" : 0.2125984251968504, + "matched_token_number" : 27 + }, + "00031_00002-00133_00001" : { + "minimal_similarity" : 0.06547619047619048, + "maximum_similarity" : 0.08870967741935484, + "matched_token_number" : 11 + }, + "00178_00002-00192_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.14838709677419354, + "matched_token_number" : 23 + }, + "00178_00002-00192_00002" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.1984732824427481, + "matched_token_number" : 26 + }, + "00013_00002-00177_00003" : { + "minimal_similarity" : 0.18452380952380953, + "maximum_similarity" : 0.23308270676691728, + "matched_token_number" : 31 + }, + "00005_00002-00160_00001" : { + "minimal_similarity" : 0.0582010582010582, + "maximum_similarity" : 0.08088235294117647, + "matched_token_number" : 11 + }, + "00014_00001-00111_00001" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00127_00002-00130_00002" : { + "minimal_similarity" : 0.3630952380952381, + "maximum_similarity" : 0.45864661654135336, + "matched_token_number" : 61 + }, + "00077_00001-00119_00001" : { + "minimal_similarity" : 0.1111111111111111, + "maximum_similarity" : 0.14, + "matched_token_number" : 21 + }, + "00000_00002-00120_00001" : { + "minimal_similarity" : 0.1310344827586207, + "maximum_similarity" : 0.13194444444444445, + "matched_token_number" : 19 + }, + "00000_00003-00120_00001" : { + "minimal_similarity" : 0.12837837837837837, + "maximum_similarity" : 0.1310344827586207, + "matched_token_number" : 19 + }, + "00013_00002-00130_00002" : { + "minimal_similarity" : 0.08270676691729323, + "maximum_similarity" : 0.08270676691729323, + "matched_token_number" : 11 + }, + "00044_00002-00097_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00111_00001-00135_00001" : { + "minimal_similarity" : 0.1956521739130435, + "maximum_similarity" : 0.21428571428571427, + "matched_token_number" : 36 + }, + "00130_00002-00131_00005" : { + "minimal_similarity" : 0.06349206349206349, + "maximum_similarity" : 0.09022556390977443, + "matched_token_number" : 12 + }, + "00000_00005-00120_00001" : { + "minimal_similarity" : 0.06711409395973154, + "maximum_similarity" : 0.06896551724137931, + "matched_token_number" : 10 + }, + "00145_00001-00192_00002" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.1984732824427481, + "matched_token_number" : 26 + }, + "00135_00001-00147_00001" : { + "minimal_similarity" : 0.08152173913043478, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00000_00003-00095_00003" : { + "minimal_similarity" : 0.09900990099009901, + "maximum_similarity" : 0.13513513513513514, + "matched_token_number" : 20 + }, + "00097_00002-00142_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00127_00002-00177_00003" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00031_00003-00192_00002" : { + "minimal_similarity" : 0.29770992366412213, + "maximum_similarity" : 0.34210526315789475, + "matched_token_number" : 39 + }, + "00192_00002-00195_00002" : { + "minimal_similarity" : 0.1111111111111111, + "maximum_similarity" : 0.1297709923664122, + "matched_token_number" : 17 + }, + "00113_00002-00199_00001" : { + "minimal_similarity" : 0.059880239520958084, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 10 + }, + "00031_00003-00192_00001" : { + "minimal_similarity" : 0.21935483870967742, + "maximum_similarity" : 0.2982456140350877, + "matched_token_number" : 34 + }, + "00145_00001-00192_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.14838709677419354, + "matched_token_number" : 23 + }, + "00000_00002-00095_00003" : { + "minimal_similarity" : 0.09900990099009901, + "maximum_similarity" : 0.1388888888888889, + "matched_token_number" : 20 + }, + "00154_00002-00156_00002" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.06707317073170732, + "matched_token_number" : 11 + }, + "00192_00002-00195_00001" : { + "minimal_similarity" : 0.1111111111111111, + "maximum_similarity" : 0.1297709923664122, + "matched_token_number" : 17 + }, + "00005_00002-00199_00001" : { + "minimal_similarity" : 0.047619047619047616, + "maximum_similarity" : 0.09473684210526316, + "matched_token_number" : 9 + }, + "00154_00002-00156_00003" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.06707317073170732, + "matched_token_number" : 11 + }, + "00000_00005-00031_00002" : { + "minimal_similarity" : 0.12751677852348994, + "maximum_similarity" : 0.1532258064516129, + "matched_token_number" : 19 + }, + "00000_00005-00031_00003" : { + "minimal_similarity" : 0.06711409395973154, + "maximum_similarity" : 0.08771929824561403, + "matched_token_number" : 10 + }, + "00156_00002-00202_00002" : { + "minimal_similarity" : 0.11797752808988764, + "maximum_similarity" : 0.14893617021276595, + "matched_token_number" : 21 + }, + "00120_00001-00137_00002" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.2482758620689655, + "matched_token_number" : 36 + }, + "00097_00002-00201_00001" : { + "minimal_similarity" : 0.06756756756756757, + "maximum_similarity" : 0.07692307692307693, + "matched_token_number" : 10 + }, + "00092_00001-00178_00002" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00133_00001-00147_00001" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00156_00002-00202_00003" : { + "minimal_similarity" : 0.11797752808988764, + "maximum_similarity" : 0.14893617021276595, + "matched_token_number" : 21 + }, + "00156_00003-00202_00002" : { + "minimal_similarity" : 0.11797752808988764, + "maximum_similarity" : 0.14893617021276595, + "matched_token_number" : 21 + }, + "00156_00003-00202_00003" : { + "minimal_similarity" : 0.11797752808988764, + "maximum_similarity" : 0.14893617021276595, + "matched_token_number" : 21 + }, + "00000_00005-00044_00002" : { + "minimal_similarity" : 0.2080536912751678, + "maximum_similarity" : 0.22794117647058823, + "matched_token_number" : 31 + }, + "00000_00002-00154_00002" : { + "minimal_similarity" : 0.054878048780487805, + "maximum_similarity" : 0.0625, + "matched_token_number" : 9 + }, + "00044_00002-00156_00002" : { + "minimal_similarity" : 0.10112359550561797, + "maximum_similarity" : 0.1323529411764706, + "matched_token_number" : 18 + }, + "00126_00002-00145_00001" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.2482758620689655, + "matched_token_number" : 36 + }, + "00044_00002-00156_00003" : { + "minimal_similarity" : 0.10112359550561797, + "maximum_similarity" : 0.1323529411764706, + "matched_token_number" : 18 + }, + "00000_00003-00154_00002" : { + "minimal_similarity" : 0.054878048780487805, + "maximum_similarity" : 0.060810810810810814, + "matched_token_number" : 9 + }, + "00154_00002-00202_00002" : { + "minimal_similarity" : 0.13414634146341464, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00113_00002-00135_00001" : { + "minimal_similarity" : 0.1956521739130435, + "maximum_similarity" : 0.2155688622754491, + "matched_token_number" : 36 + }, + "00154_00002-00202_00003" : { + "minimal_similarity" : 0.13414634146341464, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00137_00002-00142_00001" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00000_00001-00044_00002" : { + "minimal_similarity" : 0.33088235294117646, + "maximum_similarity" : 0.3543307086614173, + "matched_token_number" : 45 + }, + "00198_00001-00204_00001" : { + "minimal_similarity" : 0.1717171717171717, + "maximum_similarity" : 0.2833333333333333, + "matched_token_number" : 34 + }, + "00178_00002-00197_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.17424242424242425, + "matched_token_number" : 23 + }, + "00142_00001-00194_00001" : { + "minimal_similarity" : 0.30718954248366015, + "maximum_similarity" : 0.31333333333333335, + "matched_token_number" : 47 + }, + "00129_00008-00177_00003" : { + "minimal_similarity" : 0.10638297872340426, + "maximum_similarity" : 0.17857142857142858, + "matched_token_number" : 30 + }, + "00156_00002-00156_00003" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 178 + }, + "00186_00002-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00005-00125_00001" : { + "minimal_similarity" : 0.06547619047619048, + "maximum_similarity" : 0.0738255033557047, + "matched_token_number" : 11 + }, + "00095_00003-00192_00002" : { + "minimal_similarity" : 0.0594059405940594, + "maximum_similarity" : 0.0916030534351145, + "matched_token_number" : 12 + }, + "00000_00003-00125_00001" : { + "minimal_similarity" : 0.11904761904761904, + "maximum_similarity" : 0.13513513513513514, + "matched_token_number" : 20 + }, + "00044_00002-00202_00003" : { + "minimal_similarity" : 0.44680851063829785, + "maximum_similarity" : 0.4632352941176471, + "matched_token_number" : 63 + }, + "00013_00002-00135_00001" : { + "minimal_similarity" : 0.11413043478260869, + "maximum_similarity" : 0.15789473684210525, + "matched_token_number" : 21 + }, + "00044_00002-00202_00002" : { + "minimal_similarity" : 0.3829787234042553, + "maximum_similarity" : 0.39705882352941174, + "matched_token_number" : 54 + }, + "00111_00001-00130_00002" : { + "minimal_similarity" : 0.3630952380952381, + "maximum_similarity" : 0.45864661654135336, + "matched_token_number" : 61 + }, + "00005_00002-00194_00001" : { + "minimal_similarity" : 0.1111111111111111, + "maximum_similarity" : 0.14, + "matched_token_number" : 21 + }, + "00095_00003-00155_00001" : { + "minimal_similarity" : 0.10891089108910891, + "maximum_similarity" : 0.176, + "matched_token_number" : 22 + }, + "00160_00001-00197_00001" : { + "minimal_similarity" : 0.0661764705882353, + "maximum_similarity" : 0.06818181818181818, + "matched_token_number" : 9 + }, + "00195_00002-00198_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00001-00138_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00014_00001-00145_00001" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00095_00003-00192_00001" : { + "minimal_similarity" : 0.0594059405940594, + "maximum_similarity" : 0.07741935483870968, + "matched_token_number" : 12 + }, + "00077_00001-00203_00002" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.13793103448275862, + "matched_token_number" : 20 + }, + "00000_00002-00031_00003" : { + "minimal_similarity" : 0.14583333333333334, + "maximum_similarity" : 0.18421052631578946, + "matched_token_number" : 21 + }, + "00138_00001-00153_00001" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00197_00001-00202_00003" : { + "minimal_similarity" : 0.6028368794326241, + "maximum_similarity" : 0.6439393939393939, + "matched_token_number" : 85 + }, + "00131_00005-00147_00001" : { + "minimal_similarity" : 0.09523809523809523, + "maximum_similarity" : 0.125, + "matched_token_number" : 18 + }, + "00134_00001-00204_00001" : { + "minimal_similarity" : 0.16666666666666666, + "maximum_similarity" : 0.17094017094017094, + "matched_token_number" : 20 + }, + "00113_00002-00130_00002" : { + "minimal_similarity" : 0.3652694610778443, + "maximum_similarity" : 0.45864661654135336, + "matched_token_number" : 61 + }, + "00136_00002-00204_00001" : { + "minimal_similarity" : 0.045662100456621, + "maximum_similarity" : 0.08333333333333333, + "matched_token_number" : 10 + }, + "00187_00001-00202_00002" : { + "minimal_similarity" : 0.5390070921985816, + "maximum_similarity" : 0.5757575757575758, + "matched_token_number" : 76 + }, + "00000_00002-00031_00002" : { + "minimal_similarity" : 0.13194444444444445, + "maximum_similarity" : 0.1532258064516129, + "matched_token_number" : 19 + }, + "00187_00001-00202_00003" : { + "minimal_similarity" : 0.6028368794326241, + "maximum_similarity" : 0.6439393939393939, + "matched_token_number" : 85 + }, + "00197_00001-00202_00002" : { + "minimal_similarity" : 0.5390070921985816, + "maximum_similarity" : 0.5757575757575758, + "matched_token_number" : 76 + }, + "00121_00001-00147_00001" : { + "minimal_similarity" : 0.07772020725388601, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00000_00005-00138_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00130_00002-00178_00002" : { + "minimal_similarity" : 0.3630952380952381, + "maximum_similarity" : 0.45864661654135336, + "matched_token_number" : 61 + }, + "00153_00001-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00005_00002-00013_00002" : { + "minimal_similarity" : 0.05291005291005291, + "maximum_similarity" : 0.07518796992481203, + "matched_token_number" : 10 + }, + "00000_00002-00192_00002" : { + "minimal_similarity" : 0.2013888888888889, + "maximum_similarity" : 0.22137404580152673, + "matched_token_number" : 29 + }, + "00000_00002-00192_00001" : { + "minimal_similarity" : 0.1870967741935484, + "maximum_similarity" : 0.2013888888888889, + "matched_token_number" : 29 + }, + "00129_00008-00202_00002" : { + "minimal_similarity" : 0.07801418439716312, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00031_00002-00141_00002" : { + "minimal_similarity" : 0.07333333333333333, + "maximum_similarity" : 0.08870967741935484, + "matched_token_number" : 11 + }, + "00127_00002-00135_00001" : { + "minimal_similarity" : 0.1956521739130435, + "maximum_similarity" : 0.21428571428571427, + "matched_token_number" : 36 + }, + "00129_00008-00202_00003" : { + "minimal_similarity" : 0.07801418439716312, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00145_00001-00154_00002" : { + "minimal_similarity" : 0.8809523809523809, + "maximum_similarity" : 0.9024390243902439, + "matched_token_number" : 148 + }, + "00014_00001-00154_00002" : { + "minimal_similarity" : 0.2682926829268293, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00133_00001-00201_00001" : { + "minimal_similarity" : 0.05357142857142857, + "maximum_similarity" : 0.06923076923076923, + "matched_token_number" : 9 + }, + "00134_00001-00153_00001" : { + "minimal_similarity" : 0.1488095238095238, + "maximum_similarity" : 0.21367521367521367, + "matched_token_number" : 25 + }, + "00111_00001-00178_00002" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00095_00003-00134_00001" : { + "minimal_similarity" : 0.09405940594059406, + "maximum_similarity" : 0.1623931623931624, + "matched_token_number" : 19 + }, + "00031_00002-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00031_00003-00125_00001" : { + "minimal_similarity" : 0.14285714285714285, + "maximum_similarity" : 0.21052631578947367, + "matched_token_number" : 24 + }, + "00000_00002-00133_00001" : { + "minimal_similarity" : 0.11904761904761904, + "maximum_similarity" : 0.1388888888888889, + "matched_token_number" : 20 + }, + "00000_00005-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00133_00001-00142_00001" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00120_00001-00204_00001" : { + "minimal_similarity" : 0.0896551724137931, + "maximum_similarity" : 0.10833333333333334, + "matched_token_number" : 13 + }, + "00194_00001-00204_00001" : { + "minimal_similarity" : 0.15333333333333332, + "maximum_similarity" : 0.19166666666666668, + "matched_token_number" : 23 + }, + "00113_00002-00127_00002" : { + "minimal_similarity" : 0.9940476190476191, + "maximum_similarity" : 1.0, + "matched_token_number" : 167 + }, + "00113_00002-00160_00001" : { + "minimal_similarity" : 0.1317365269461078, + "maximum_similarity" : 0.16176470588235295, + "matched_token_number" : 22 + }, + "00142_00001-00186_00002" : { + "minimal_similarity" : 0.09090909090909091, + "maximum_similarity" : 0.10457516339869281, + "matched_token_number" : 16 + }, + "00095_00003-00133_00001" : { + "minimal_similarity" : 0.11386138613861387, + "maximum_similarity" : 0.13690476190476192, + "matched_token_number" : 23 + }, + "00031_00002-00138_00001" : { + "minimal_similarity" : 0.0763888888888889, + "maximum_similarity" : 0.08870967741935484, + "matched_token_number" : 11 + }, + "00120_00001-00145_00001" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.2482758620689655, + "matched_token_number" : 36 + }, + "00000_00005-00197_00001" : { + "minimal_similarity" : 0.14093959731543623, + "maximum_similarity" : 0.1590909090909091, + "matched_token_number" : 21 + }, + "00147_00001-00197_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00014_00001-00153_00001" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00142_00001-00186_00004" : { + "minimal_similarity" : 0.10457516339869281, + "maximum_similarity" : 0.1111111111111111, + "matched_token_number" : 16 + }, + "00145_00001-00184_00002" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.2765957446808511, + "matched_token_number" : 26 + }, + "00111_00001-00177_00003" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00097_00002-00134_00001" : { + "minimal_similarity" : 0.20945945945945946, + "maximum_similarity" : 0.26495726495726496, + "matched_token_number" : 31 + }, + "00193_00001-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00140_00001-00203_00002" : { + "minimal_similarity" : 0.0896551724137931, + "maximum_similarity" : 0.09774436090225563, + "matched_token_number" : 13 + }, + "00125_00001-00156_00003" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00125_00001-00156_00002" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00092_00001-00186_00002" : { + "minimal_similarity" : 0.056818181818181816, + "maximum_similarity" : 0.06944444444444445, + "matched_token_number" : 10 + }, + "00121_00001-00177_00003" : { + "minimal_similarity" : 0.7046632124352331, + "maximum_similarity" : 0.8095238095238095, + "matched_token_number" : 136 + }, + "00031_00002-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00092_00001-00186_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00031_00003-00044_00002" : { + "minimal_similarity" : 0.20588235294117646, + "maximum_similarity" : 0.24561403508771928, + "matched_token_number" : 28 + }, + "00119_00001-00186_00002" : { + "minimal_similarity" : 0.1534090909090909, + "maximum_similarity" : 0.18, + "matched_token_number" : 27 + }, + "00119_00001-00186_00004" : { + "minimal_similarity" : 0.17333333333333334, + "maximum_similarity" : 0.18055555555555555, + "matched_token_number" : 26 + }, + "00141_00002-00200_00002" : { + "minimal_similarity" : 0.058823529411764705, + "maximum_similarity" : 0.06666666666666667, + "matched_token_number" : 10 + }, + "00177_00003-00203_00002" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.15862068965517243, + "matched_token_number" : 23 + }, + "00135_00001-00184_00002" : { + "minimal_similarity" : 0.05434782608695652, + "maximum_similarity" : 0.10638297872340426, + "matched_token_number" : 10 + }, + "00145_00001-00184_00003" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.2765957446808511, + "matched_token_number" : 26 + }, + "00135_00001-00184_00003" : { + "minimal_similarity" : 0.05434782608695652, + "maximum_similarity" : 0.10638297872340426, + "matched_token_number" : 10 + }, + "00147_00001-00155_00001" : { + "minimal_similarity" : 0.10416666666666667, + "maximum_similarity" : 0.12, + "matched_token_number" : 15 + }, + "00153_00001-00154_00002" : { + "minimal_similarity" : 0.8809523809523809, + "maximum_similarity" : 0.9024390243902439, + "matched_token_number" : 148 + }, + "00126_00002-00141_00002" : { + "minimal_similarity" : 0.31333333333333335, + "maximum_similarity" : 0.32413793103448274, + "matched_token_number" : 47 + }, + "00131_00005-00133_00001" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00129_00008-00186_00004" : { + "minimal_similarity" : 0.0425531914893617, + "maximum_similarity" : 0.08333333333333333, + "matched_token_number" : 12 + }, + "00129_00008-00186_00002" : { + "minimal_similarity" : 0.0425531914893617, + "maximum_similarity" : 0.06818181818181818, + "matched_token_number" : 12 + }, + "00125_00001-00147_00001" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00137_00002-00177_00003" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00193_00001-00202_00003" : { + "minimal_similarity" : 0.11515151515151516, + "maximum_similarity" : 0.1347517730496454, + "matched_token_number" : 19 + }, + "00197_00001-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00193_00001-00202_00002" : { + "minimal_similarity" : 0.12727272727272726, + "maximum_similarity" : 0.14893617021276595, + "matched_token_number" : 21 + }, + "00000_00005-00129_00008" : { + "minimal_similarity" : 0.031914893617021274, + "maximum_similarity" : 0.06040268456375839, + "matched_token_number" : 9 + }, + "00137_00002-00184_00003" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.2765957446808511, + "matched_token_number" : 26 + }, + "00031_00003-00196_00001" : { + "minimal_similarity" : 0.024793388429752067, + "maximum_similarity" : 0.07894736842105263, + "matched_token_number" : 9 + }, + "00160_00001-00198_00001" : { + "minimal_similarity" : 0.05555555555555555, + "maximum_similarity" : 0.08088235294117647, + "matched_token_number" : 11 + }, + "00137_00002-00184_00002" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.2765957446808511, + "matched_token_number" : 26 + }, + "00095_00003-00120_00001" : { + "minimal_similarity" : 0.0594059405940594, + "maximum_similarity" : 0.08275862068965517, + "matched_token_number" : 12 + }, + "00126_00002-00204_00001" : { + "minimal_similarity" : 0.0896551724137931, + "maximum_similarity" : 0.10833333333333334, + "matched_token_number" : 13 + }, + "00195_00002-00197_00001" : { + "minimal_similarity" : 0.08496732026143791, + "maximum_similarity" : 0.09848484848484848, + "matched_token_number" : 13 + }, + "00113_00002-00136_00002" : { + "minimal_similarity" : 0.0867579908675799, + "maximum_similarity" : 0.11377245508982035, + "matched_token_number" : 19 + }, + "00095_00003-00126_00002" : { + "minimal_similarity" : 0.0594059405940594, + "maximum_similarity" : 0.08275862068965517, + "matched_token_number" : 12 + }, + "00111_00001-00202_00003" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00014_00001-00204_00001" : { + "minimal_similarity" : 0.15333333333333332, + "maximum_similarity" : 0.19166666666666668, + "matched_token_number" : 23 + }, + "00111_00001-00202_00002" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00131_00005-00138_00001" : { + "minimal_similarity" : 0.09523809523809523, + "maximum_similarity" : 0.125, + "matched_token_number" : 18 + }, + "00031_00003-00129_00008" : { + "minimal_similarity" : 0.0425531914893617, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 12 + }, + "00125_00001-00142_00001" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00127_00002-00147_00001" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00000_00005-00137_00002" : { + "minimal_similarity" : 0.06547619047619048, + "maximum_similarity" : 0.0738255033557047, + "matched_token_number" : 11 + }, + "00156_00003-00203_00002" : { + "minimal_similarity" : 0.06741573033707865, + "maximum_similarity" : 0.08275862068965517, + "matched_token_number" : 12 + }, + "00111_00001-00203_00002" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.15862068965517243, + "matched_token_number" : 23 + }, + "00129_00008-00178_00002" : { + "minimal_similarity" : 0.10638297872340426, + "maximum_similarity" : 0.17857142857142858, + "matched_token_number" : 30 + }, + "00131_00005-00134_00001" : { + "minimal_similarity" : 0.047619047619047616, + "maximum_similarity" : 0.07692307692307693, + "matched_token_number" : 9 + }, + "00097_00002-00138_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00001-00201_00001" : { + "minimal_similarity" : 0.06923076923076923, + "maximum_similarity" : 0.07086614173228346, + "matched_token_number" : 9 + }, + "00044_00002-00203_00002" : { + "minimal_similarity" : 0.2689655172413793, + "maximum_similarity" : 0.2867647058823529, + "matched_token_number" : 39 + }, + "00095_00003-00125_00001" : { + "minimal_similarity" : 0.11386138613861387, + "maximum_similarity" : 0.13690476190476192, + "matched_token_number" : 23 + }, + "00147_00001-00154_00002" : { + "minimal_similarity" : 0.07926829268292683, + "maximum_similarity" : 0.09027777777777778, + "matched_token_number" : 13 + }, + "00113_00002-00198_00001" : { + "minimal_similarity" : 0.18686868686868688, + "maximum_similarity" : 0.2215568862275449, + "matched_token_number" : 37 + }, + "00127_00002-00142_00001" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00199_00001-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00141_00002-00145_00001" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00126_00002-00133_00001" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.2482758620689655, + "matched_token_number" : 36 + }, + "00154_00002-00155_00001" : { + "minimal_similarity" : 0.23780487804878048, + "maximum_similarity" : 0.312, + "matched_token_number" : 39 + }, + "00031_00002-00111_00001" : { + "minimal_similarity" : 0.06547619047619048, + "maximum_similarity" : 0.08870967741935484, + "matched_token_number" : 11 + }, + "00000_00001-00137_00002" : { + "minimal_similarity" : 0.1488095238095238, + "maximum_similarity" : 0.1968503937007874, + "matched_token_number" : 25 + }, + "00097_00002-00202_00003" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00145_00001-00197_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.17424242424242425, + "matched_token_number" : 23 + }, + "00097_00002-00202_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00003-00155_00001" : { + "minimal_similarity" : 0.060810810810810814, + "maximum_similarity" : 0.072, + "matched_token_number" : 9 + }, + "00126_00002-00138_00001" : { + "minimal_similarity" : 0.12413793103448276, + "maximum_similarity" : 0.125, + "matched_token_number" : 18 + }, + "00097_00002-00147_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00154_00002-00203_00002" : { + "minimal_similarity" : 0.1402439024390244, + "maximum_similarity" : 0.15862068965517243, + "matched_token_number" : 23 + }, + "00000_00002-00125_00001" : { + "minimal_similarity" : 0.11904761904761904, + "maximum_similarity" : 0.1388888888888889, + "matched_token_number" : 20 + }, + "00044_00002-00147_00001" : { + "minimal_similarity" : 0.06944444444444445, + "maximum_similarity" : 0.07352941176470588, + "matched_token_number" : 10 + }, + "00031_00003-00197_00001" : { + "minimal_similarity" : 0.26515151515151514, + "maximum_similarity" : 0.30701754385964913, + "matched_token_number" : 35 + }, + "00031_00003-00137_00002" : { + "minimal_similarity" : 0.14285714285714285, + "maximum_similarity" : 0.21052631578947367, + "matched_token_number" : 24 + }, + "00031_00002-00147_00001" : { + "minimal_similarity" : 0.0763888888888889, + "maximum_similarity" : 0.08870967741935484, + "matched_token_number" : 11 + }, + "00000_00001-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00126_00002-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00133_00001-00154_00002" : { + "minimal_similarity" : 0.8809523809523809, + "maximum_similarity" : 0.9024390243902439, + "matched_token_number" : 148 + }, + "00199_00001-00202_00002" : { + "minimal_similarity" : 0.07092198581560284, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 10 + }, + "00131_00005-00202_00003" : { + "minimal_similarity" : 0.1693121693121693, + "maximum_similarity" : 0.22695035460992907, + "matched_token_number" : 32 + }, + "00199_00001-00202_00003" : { + "minimal_similarity" : 0.07092198581560284, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 10 + }, + "00125_00001-00203_00002" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.15862068965517243, + "matched_token_number" : 23 + }, + "00014_00001-00200_00002" : { + "minimal_similarity" : 0.058823529411764705, + "maximum_similarity" : 0.06666666666666667, + "matched_token_number" : 10 + }, + "00000_00005-00192_00001" : { + "minimal_similarity" : 0.12903225806451613, + "maximum_similarity" : 0.1342281879194631, + "matched_token_number" : 20 + }, + "00077_00001-00113_00002" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.11377245508982035, + "matched_token_number" : 19 + }, + "00000_00005-00192_00002" : { + "minimal_similarity" : 0.1342281879194631, + "maximum_similarity" : 0.15267175572519084, + "matched_token_number" : 20 + }, + "00111_00001-00136_00002" : { + "minimal_similarity" : 0.0867579908675799, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00183_00004-00203_00002" : { + "minimal_similarity" : 0.061224489795918366, + "maximum_similarity" : 0.06206896551724138, + "matched_token_number" : 9 + }, + "00131_00005-00202_00002" : { + "minimal_similarity" : 0.21693121693121692, + "maximum_similarity" : 0.2907801418439716, + "matched_token_number" : 41 + }, + "00126_00002-00140_00001" : { + "minimal_similarity" : 0.18620689655172415, + "maximum_similarity" : 0.20300751879699247, + "matched_token_number" : 27 + }, + "00138_00001-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00125_00001-00201_00001" : { + "minimal_similarity" : 0.05357142857142857, + "maximum_similarity" : 0.06923076923076923, + "matched_token_number" : 9 + }, + "00113_00002-00193_00001" : { + "minimal_similarity" : 0.0718562874251497, + "maximum_similarity" : 0.07272727272727272, + "matched_token_number" : 12 + }, + "00186_00002-00192_00001" : { + "minimal_similarity" : 0.30113636363636365, + "maximum_similarity" : 0.3419354838709677, + "matched_token_number" : 53 + }, + "00000_00001-00140_00001" : { + "minimal_similarity" : 0.12030075187969924, + "maximum_similarity" : 0.12598425196850394, + "matched_token_number" : 16 + }, + "00133_00001-00156_00002" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00186_00002-00192_00002" : { + "minimal_similarity" : 0.29545454545454547, + "maximum_similarity" : 0.3969465648854962, + "matched_token_number" : 52 + }, + "00140_00001-00156_00003" : { + "minimal_similarity" : 0.06741573033707865, + "maximum_similarity" : 0.09022556390977443, + "matched_token_number" : 12 + }, + "00133_00001-00156_00003" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00131_00005-00141_00002" : { + "minimal_similarity" : 0.1111111111111111, + "maximum_similarity" : 0.14, + "matched_token_number" : 21 + }, + "00198_00001-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00127_00002-00202_00002" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00183_00004-00202_00002" : { + "minimal_similarity" : 0.08163265306122448, + "maximum_similarity" : 0.0851063829787234, + "matched_token_number" : 12 + }, + "00031_00002-00044_00002" : { + "minimal_similarity" : 0.22058823529411764, + "maximum_similarity" : 0.24193548387096775, + "matched_token_number" : 30 + }, + "00014_00001-00187_00001" : { + "minimal_similarity" : 0.08666666666666667, + "maximum_similarity" : 0.09848484848484848, + "matched_token_number" : 13 + }, + "00140_00001-00156_00002" : { + "minimal_similarity" : 0.06741573033707865, + "maximum_similarity" : 0.09022556390977443, + "matched_token_number" : 12 + }, + "00127_00002-00202_00003" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00183_00004-00202_00003" : { + "minimal_similarity" : 0.07482993197278912, + "maximum_similarity" : 0.07801418439716312, + "matched_token_number" : 11 + }, + "00000_00005-00133_00001" : { + "minimal_similarity" : 0.06547619047619048, + "maximum_similarity" : 0.0738255033557047, + "matched_token_number" : 11 + }, + "00192_00001-00203_00002" : { + "minimal_similarity" : 0.36774193548387096, + "maximum_similarity" : 0.3931034482758621, + "matched_token_number" : 57 + }, + "00014_00001-00140_00001" : { + "minimal_similarity" : 0.32666666666666666, + "maximum_similarity" : 0.3684210526315789, + "matched_token_number" : 49 + }, + "00138_00001-00195_00001" : { + "minimal_similarity" : 0.11764705882352941, + "maximum_similarity" : 0.125, + "matched_token_number" : 18 + }, + "00092_00001-00119_00001" : { + "minimal_similarity" : 0.1, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00138_00001-00195_00002" : { + "minimal_similarity" : 0.11764705882352941, + "maximum_similarity" : 0.125, + "matched_token_number" : 18 + }, + "00126_00002-00137_00002" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.2482758620689655, + "matched_token_number" : 36 + }, + "00000_00001-00133_00001" : { + "minimal_similarity" : 0.1488095238095238, + "maximum_similarity" : 0.1968503937007874, + "matched_token_number" : 25 + }, + "00113_00002-00195_00001" : { + "minimal_similarity" : 0.2155688622754491, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00119_00001-00204_00001" : { + "minimal_similarity" : 0.15333333333333332, + "maximum_similarity" : 0.19166666666666668, + "matched_token_number" : 23 + }, + "00113_00002-00195_00002" : { + "minimal_similarity" : 0.2155688622754491, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00031_00003-00138_00001" : { + "minimal_similarity" : 0.06944444444444445, + "maximum_similarity" : 0.08771929824561403, + "matched_token_number" : 10 + }, + "00145_00001-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00003-00111_00001" : { + "minimal_similarity" : 0.11904761904761904, + "maximum_similarity" : 0.13513513513513514, + "matched_token_number" : 20 + }, + "00000_00005-00134_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00133_00001-00155_00001" : { + "minimal_similarity" : 0.30357142857142855, + "maximum_similarity" : 0.408, + "matched_token_number" : 51 + }, + "00131_00005-00142_00001" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.13071895424836602, + "matched_token_number" : 20 + }, + "00095_00003-00121_00001" : { + "minimal_similarity" : 0.11386138613861387, + "maximum_similarity" : 0.11917098445595854, + "matched_token_number" : 23 + }, + "00183_00004-00201_00001" : { + "minimal_similarity" : 0.16326530612244897, + "maximum_similarity" : 0.18461538461538463, + "matched_token_number" : 24 + }, + "00125_00001-00202_00002" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00125_00001-00202_00003" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00127_00002-00203_00002" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.15862068965517243, + "matched_token_number" : 23 + }, + "00000_00001-00134_00001" : { + "minimal_similarity" : 0.09448818897637795, + "maximum_similarity" : 0.10256410256410256, + "matched_token_number" : 12 + }, + "00131_00005-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00126_00002-00136_00002" : { + "minimal_similarity" : 0.0547945205479452, + "maximum_similarity" : 0.08275862068965517, + "matched_token_number" : 12 + }, + "00192_00001-00204_00001" : { + "minimal_similarity" : 0.2, + "maximum_similarity" : 0.25833333333333336, + "matched_token_number" : 31 + }, + "00014_00001-00141_00002" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 150 + }, + "00138_00001-00194_00001" : { + "minimal_similarity" : 0.1, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00129_00008-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00121_00001-00178_00002" : { + "minimal_similarity" : 0.7046632124352331, + "maximum_similarity" : 0.8095238095238095, + "matched_token_number" : 136 + }, + "00077_00001-00147_00001" : { + "minimal_similarity" : 0.09523809523809523, + "maximum_similarity" : 0.125, + "matched_token_number" : 18 + }, + "00147_00001-00198_00001" : { + "minimal_similarity" : 0.050505050505050504, + "maximum_similarity" : 0.06944444444444445, + "matched_token_number" : 10 + }, + "00092_00001-00111_00001" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00092_00001-00202_00003" : { + "minimal_similarity" : 0.08333333333333333, + "maximum_similarity" : 0.0851063829787234, + "matched_token_number" : 12 + }, + "00140_00001-00187_00001" : { + "minimal_similarity" : 0.09774436090225563, + "maximum_similarity" : 0.09848484848484848, + "matched_token_number" : 13 + }, + "00121_00001-00203_00002" : { + "minimal_similarity" : 0.07772020725388601, + "maximum_similarity" : 0.10344827586206896, + "matched_token_number" : 15 + }, + "00092_00001-00202_00002" : { + "minimal_similarity" : 0.08333333333333333, + "maximum_similarity" : 0.0851063829787234, + "matched_token_number" : 12 + }, + "00154_00002-00184_00002" : { + "minimal_similarity" : 0.15853658536585366, + "maximum_similarity" : 0.2765957446808511, + "matched_token_number" : 26 + }, + "00154_00002-00184_00003" : { + "minimal_similarity" : 0.15853658536585366, + "maximum_similarity" : 0.2765957446808511, + "matched_token_number" : 26 + }, + "00145_00001-00193_00001" : { + "minimal_similarity" : 0.07142857142857142, + "maximum_similarity" : 0.07272727272727272, + "matched_token_number" : 12 + }, + "00113_00002-00134_00001" : { + "minimal_similarity" : 0.1497005988023952, + "maximum_similarity" : 0.21367521367521367, + "matched_token_number" : 25 + }, + "00092_00001-00177_00003" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00031_00002-00140_00001" : { + "minimal_similarity" : 0.13533834586466165, + "maximum_similarity" : 0.14516129032258066, + "matched_token_number" : 18 + }, + "00153_00001-00197_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.17424242424242425, + "matched_token_number" : 23 + }, + "00013_00002-00131_00005" : { + "minimal_similarity" : 0.05291005291005291, + "maximum_similarity" : 0.07518796992481203, + "matched_token_number" : 10 + }, + "00127_00002-00201_00001" : { + "minimal_similarity" : 0.05357142857142857, + "maximum_similarity" : 0.06923076923076923, + "matched_token_number" : 9 + }, + "00142_00001-00153_00001" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00120_00001-00178_00002" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.2482758620689655, + "matched_token_number" : 36 + }, + "00095_00003-00129_00008" : { + "minimal_similarity" : 0.09219858156028368, + "maximum_similarity" : 0.12871287128712872, + "matched_token_number" : 26 + }, + "00000_00003-00187_00001" : { + "minimal_similarity" : 0.20270270270270271, + "maximum_similarity" : 0.22727272727272727, + "matched_token_number" : 30 + }, + "00141_00002-00147_00001" : { + "minimal_similarity" : 0.1, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00186_00004-00201_00001" : { + "minimal_similarity" : 0.0625, + "maximum_similarity" : 0.06923076923076923, + "matched_token_number" : 9 + }, + "00014_00001-00201_00001" : { + "minimal_similarity" : 0.24, + "maximum_similarity" : 0.27692307692307694, + "matched_token_number" : 36 + }, + "00156_00003-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00077_00001-00142_00001" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.13071895424836602, + "matched_token_number" : 20 + }, + "00147_00001-00193_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00002-00193_00001" : { + "minimal_similarity" : 0.06666666666666667, + "maximum_similarity" : 0.0763888888888889, + "matched_token_number" : 11 + }, + "00014_00001-00184_00002" : { + "minimal_similarity" : 0.18, + "maximum_similarity" : 0.2872340425531915, + "matched_token_number" : 27 + }, + "00014_00001-00184_00003" : { + "minimal_similarity" : 0.18, + "maximum_similarity" : 0.2872340425531915, + "matched_token_number" : 27 + }, + "00192_00001-00200_00002" : { + "minimal_similarity" : 0.052941176470588235, + "maximum_similarity" : 0.05806451612903226, + "matched_token_number" : 9 + }, + "00097_00002-00200_00002" : { + "minimal_similarity" : 0.07647058823529412, + "maximum_similarity" : 0.08783783783783784, + "matched_token_number" : 13 + }, + "00000_00005-00193_00001" : { + "minimal_similarity" : 0.06666666666666667, + "maximum_similarity" : 0.0738255033557047, + "matched_token_number" : 11 + }, + "00134_00001-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00156_00002-00184_00003" : { + "minimal_similarity" : 0.06741573033707865, + "maximum_similarity" : 0.1276595744680851, + "matched_token_number" : 12 + }, + "00156_00002-00184_00002" : { + "minimal_similarity" : 0.06741573033707865, + "maximum_similarity" : 0.1276595744680851, + "matched_token_number" : 12 + }, + "00186_00002-00195_00001" : { + "minimal_similarity" : 0.09090909090909091, + "maximum_similarity" : 0.10457516339869281, + "matched_token_number" : 16 + }, + "00031_00002-00145_00001" : { + "minimal_similarity" : 0.06547619047619048, + "maximum_similarity" : 0.08870967741935484, + "matched_token_number" : 11 + }, + "00186_00002-00195_00002" : { + "minimal_similarity" : 0.09090909090909091, + "maximum_similarity" : 0.10457516339869281, + "matched_token_number" : 16 + }, + "00178_00002-00198_00001" : { + "minimal_similarity" : 0.18686868686868688, + "maximum_similarity" : 0.22023809523809523, + "matched_token_number" : 37 + }, + "00031_00003-00198_00001" : { + "minimal_similarity" : 0.10101010101010101, + "maximum_similarity" : 0.17543859649122806, + "matched_token_number" : 20 + }, + "00005_00002-00137_00002" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00000_00003-00113_00002" : { + "minimal_similarity" : 0.11976047904191617, + "maximum_similarity" : 0.13513513513513514, + "matched_token_number" : 20 + }, + "00187_00001-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00003-00153_00001" : { + "minimal_similarity" : 0.11904761904761904, + "maximum_similarity" : 0.13513513513513514, + "matched_token_number" : 20 + }, + "00153_00001-00192_00002" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.1984732824427481, + "matched_token_number" : 26 + }, + "00134_00001-00156_00002" : { + "minimal_similarity" : 0.0898876404494382, + "maximum_similarity" : 0.13675213675213677, + "matched_token_number" : 16 + }, + "00153_00001-00192_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.14838709677419354, + "matched_token_number" : 23 + }, + "00134_00001-00156_00003" : { + "minimal_similarity" : 0.0898876404494382, + "maximum_similarity" : 0.13675213675213677, + "matched_token_number" : 16 + }, + "00198_00001-00203_00002" : { + "minimal_similarity" : 0.08080808080808081, + "maximum_similarity" : 0.1103448275862069, + "matched_token_number" : 16 + }, + "00137_00002-00141_00002" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00130_00002-00137_00002" : { + "minimal_similarity" : 0.3630952380952381, + "maximum_similarity" : 0.45864661654135336, + "matched_token_number" : 61 + }, + "00141_00002-00204_00001" : { + "minimal_similarity" : 0.15333333333333332, + "maximum_similarity" : 0.19166666666666668, + "matched_token_number" : 23 + }, + "00013_00002-00136_00002" : { + "minimal_similarity" : 0.0410958904109589, + "maximum_similarity" : 0.06766917293233082, + "matched_token_number" : 9 + }, + "00000_00002-00126_00002" : { + "minimal_similarity" : 0.1310344827586207, + "maximum_similarity" : 0.13194444444444445, + "matched_token_number" : 19 + }, + "00145_00001-00153_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00196_00001-00203_00002" : { + "minimal_similarity" : 0.024793388429752067, + "maximum_similarity" : 0.06206896551724138, + "matched_token_number" : 9 + }, + "00044_00002-00184_00003" : { + "minimal_similarity" : 0.125, + "maximum_similarity" : 0.18085106382978725, + "matched_token_number" : 17 + }, + "00044_00002-00184_00002" : { + "minimal_similarity" : 0.125, + "maximum_similarity" : 0.18085106382978725, + "matched_token_number" : 17 + }, + "00129_00008-00142_00001" : { + "minimal_similarity" : 0.0425531914893617, + "maximum_similarity" : 0.0784313725490196, + "matched_token_number" : 12 + }, + "00192_00002-00194_00001" : { + "minimal_similarity" : 0.11333333333333333, + "maximum_similarity" : 0.1297709923664122, + "matched_token_number" : 17 + }, + "00097_00002-00177_00003" : { + "minimal_similarity" : 0.07738095238095238, + "maximum_similarity" : 0.08783783783783784, + "matched_token_number" : 13 + }, + "00140_00001-00153_00001" : { + "minimal_similarity" : 0.3630952380952381, + "maximum_similarity" : 0.45864661654135336, + "matched_token_number" : 61 + }, + "00031_00003-00134_00001" : { + "minimal_similarity" : 0.18803418803418803, + "maximum_similarity" : 0.19298245614035087, + "matched_token_number" : 22 + }, + "00184_00002-00195_00002" : { + "minimal_similarity" : 0.1111111111111111, + "maximum_similarity" : 0.18085106382978725, + "matched_token_number" : 17 + }, + "00031_00002-00204_00001" : { + "minimal_similarity" : 0.14516129032258066, + "maximum_similarity" : 0.15, + "matched_token_number" : 18 + }, + "00184_00002-00195_00001" : { + "minimal_similarity" : 0.1111111111111111, + "maximum_similarity" : 0.18085106382978725, + "matched_token_number" : 17 + }, + "00137_00002-00200_00002" : { + "minimal_similarity" : 0.06470588235294118, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00044_00002-00187_00001" : { + "minimal_similarity" : 0.40441176470588236, + "maximum_similarity" : 0.4166666666666667, + "matched_token_number" : 55 + }, + "00194_00001-00203_00002" : { + "minimal_similarity" : 0.15333333333333332, + "maximum_similarity" : 0.15862068965517243, + "matched_token_number" : 23 + }, + "00000_00005-00198_00001" : { + "minimal_similarity" : 0.05555555555555555, + "maximum_similarity" : 0.0738255033557047, + "matched_token_number" : 11 + }, + "00186_00002-00197_00001" : { + "minimal_similarity" : 0.3125, + "maximum_similarity" : 0.4166666666666667, + "matched_token_number" : 55 + }, + "00031_00002-00202_00003" : { + "minimal_similarity" : 0.2198581560283688, + "maximum_similarity" : 0.25, + "matched_token_number" : 31 + }, + "00126_00002-00178_00002" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.2482758620689655, + "matched_token_number" : 36 + }, + "00155_00001-00192_00001" : { + "minimal_similarity" : 0.10967741935483871, + "maximum_similarity" : 0.136, + "matched_token_number" : 17 + }, + "00155_00001-00192_00002" : { + "minimal_similarity" : 0.13740458015267176, + "maximum_similarity" : 0.144, + "matched_token_number" : 18 + }, + "00031_00002-00202_00002" : { + "minimal_similarity" : 0.15602836879432624, + "maximum_similarity" : 0.1774193548387097, + "matched_token_number" : 22 + }, + "00192_00002-00196_00001" : { + "minimal_similarity" : 0.049586776859504134, + "maximum_similarity" : 0.13740458015267176, + "matched_token_number" : 18 + }, + "00160_00001-00194_00001" : { + "minimal_similarity" : 0.08, + "maximum_similarity" : 0.08823529411764706, + "matched_token_number" : 12 + }, + "00142_00001-00155_00001" : { + "minimal_similarity" : 0.23529411764705882, + "maximum_similarity" : 0.288, + "matched_token_number" : 36 + }, + "00178_00002-00193_00001" : { + "minimal_similarity" : 0.07142857142857142, + "maximum_similarity" : 0.07272727272727272, + "matched_token_number" : 12 + }, + "00134_00001-00154_00002" : { + "minimal_similarity" : 0.2073170731707317, + "maximum_similarity" : 0.2905982905982906, + "matched_token_number" : 34 + }, + "00178_00002-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00192_00002-00199_00001" : { + "minimal_similarity" : 0.08396946564885496, + "maximum_similarity" : 0.11578947368421053, + "matched_token_number" : 11 + }, + "00135_00001-00183_00004" : { + "minimal_similarity" : 0.04891304347826087, + "maximum_similarity" : 0.061224489795918366, + "matched_token_number" : 9 + }, + "00135_00001-00186_00002" : { + "minimal_similarity" : 0.10869565217391304, + "maximum_similarity" : 0.11363636363636363, + "matched_token_number" : 20 + }, + "00092_00001-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00193_00001-00203_00002" : { + "minimal_similarity" : 0.13333333333333333, + "maximum_similarity" : 0.15172413793103448, + "matched_token_number" : 22 + }, + "00125_00001-00186_00002" : { + "minimal_similarity" : 0.1534090909090909, + "maximum_similarity" : 0.16071428571428573, + "matched_token_number" : 27 + }, + "00193_00001-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00130_00002-00135_00001" : { + "minimal_similarity" : 0.20652173913043478, + "maximum_similarity" : 0.2857142857142857, + "matched_token_number" : 38 + }, + "00097_00002-00141_00002" : { + "minimal_similarity" : 0.18666666666666668, + "maximum_similarity" : 0.1891891891891892, + "matched_token_number" : 28 + }, + "00125_00001-00186_00004" : { + "minimal_similarity" : 0.16666666666666666, + "maximum_similarity" : 0.19444444444444445, + "matched_token_number" : 28 + }, + "00135_00001-00186_00004" : { + "minimal_similarity" : 0.16304347826086957, + "maximum_similarity" : 0.20833333333333334, + "matched_token_number" : 30 + }, + "00127_00002-00178_00002" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00137_00002-00178_00002" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00135_00001-00154_00002" : { + "minimal_similarity" : 0.27717391304347827, + "maximum_similarity" : 0.31097560975609756, + "matched_token_number" : 51 + }, + "00129_00008-00147_00001" : { + "minimal_similarity" : 0.031914893617021274, + "maximum_similarity" : 0.0625, + "matched_token_number" : 9 + }, + "00000_00001-00014_00001" : { + "minimal_similarity" : 0.18, + "maximum_similarity" : 0.2125984251968504, + "matched_token_number" : 27 + }, + "00092_00001-00113_00002" : { + "minimal_similarity" : 0.08982035928143713, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00000_00005-00195_00002" : { + "minimal_similarity" : 0.06535947712418301, + "maximum_similarity" : 0.06711409395973154, + "matched_token_number" : 10 + }, + "00000_00005-00195_00001" : { + "minimal_similarity" : 0.06535947712418301, + "maximum_similarity" : 0.06711409395973154, + "matched_token_number" : 10 + }, + "00031_00002-00142_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00197_00001-00203_00002" : { + "minimal_similarity" : 0.5103448275862069, + "maximum_similarity" : 0.5606060606060606, + "matched_token_number" : 74 + }, + "00142_00001-00187_00001" : { + "minimal_similarity" : 0.08496732026143791, + "maximum_similarity" : 0.09848484848484848, + "matched_token_number" : 13 + }, + "00145_00001-00155_00001" : { + "minimal_similarity" : 0.30357142857142855, + "maximum_similarity" : 0.408, + "matched_token_number" : 51 + }, + "00141_00002-00201_00001" : { + "minimal_similarity" : 0.24, + "maximum_similarity" : 0.27692307692307694, + "matched_token_number" : 36 + }, + "00013_00002-00133_00001" : { + "minimal_similarity" : 0.18452380952380953, + "maximum_similarity" : 0.23308270676691728, + "matched_token_number" : 31 + }, + "00014_00001-00147_00001" : { + "minimal_similarity" : 0.1, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00077_00001-00145_00001" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00147_00001-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00154_00002-00186_00004" : { + "minimal_similarity" : 0.17073170731707318, + "maximum_similarity" : 0.19444444444444445, + "matched_token_number" : 28 + }, + "00095_00003-00127_00002" : { + "minimal_similarity" : 0.11386138613861387, + "maximum_similarity" : 0.13690476190476192, + "matched_token_number" : 23 + }, + "00154_00002-00186_00002" : { + "minimal_similarity" : 0.1534090909090909, + "maximum_similarity" : 0.16463414634146342, + "matched_token_number" : 27 + }, + "00136_00002-00177_00003" : { + "minimal_similarity" : 0.0867579908675799, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00129_00008-00203_00002" : { + "minimal_similarity" : 0.0425531914893617, + "maximum_similarity" : 0.08275862068965517, + "matched_token_number" : 12 + }, + "00155_00001-00160_00001" : { + "minimal_similarity" : 0.25, + "maximum_similarity" : 0.272, + "matched_token_number" : 34 + }, + "00119_00001-00187_00001" : { + "minimal_similarity" : 0.08666666666666667, + "maximum_similarity" : 0.09848484848484848, + "matched_token_number" : 13 + }, + "00187_00001-00204_00001" : { + "minimal_similarity" : 0.3939393939393939, + "maximum_similarity" : 0.43333333333333335, + "matched_token_number" : 52 + }, + "00141_00002-00142_00001" : { + "minimal_similarity" : 0.30718954248366015, + "maximum_similarity" : 0.31333333333333335, + "matched_token_number" : 47 + }, + "00044_00002-00113_00002" : { + "minimal_similarity" : 0.16167664670658682, + "maximum_similarity" : 0.19852941176470587, + "matched_token_number" : 27 + }, + "00196_00001-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00131_00005-00177_00003" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00153_00001-00195_00002" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00184_00002-00192_00002" : { + "minimal_similarity" : 0.16030534351145037, + "maximum_similarity" : 0.22340425531914893, + "matched_token_number" : 21 + }, + "00145_00001-00156_00002" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00154_00002-00187_00001" : { + "minimal_similarity" : 0.1402439024390244, + "maximum_similarity" : 0.17424242424242425, + "matched_token_number" : 23 + }, + "00145_00001-00156_00003" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00153_00001-00195_00001" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.23529411764705882, + "matched_token_number" : 36 + }, + "00135_00001-00156_00003" : { + "minimal_similarity" : 0.11956521739130435, + "maximum_similarity" : 0.12359550561797752, + "matched_token_number" : 22 + }, + "00129_00008-00204_00001" : { + "minimal_similarity" : 0.07801418439716312, + "maximum_similarity" : 0.18333333333333332, + "matched_token_number" : 22 + }, + "00135_00001-00156_00002" : { + "minimal_similarity" : 0.11956521739130435, + "maximum_similarity" : 0.12359550561797752, + "matched_token_number" : 22 + }, + "00184_00002-00192_00001" : { + "minimal_similarity" : 0.09032258064516129, + "maximum_similarity" : 0.14893617021276595, + "matched_token_number" : 14 + }, + "00160_00001-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00092_00001-00140_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00120_00001-00203_00002" : { + "minimal_similarity" : 0.15172413793103448, + "maximum_similarity" : 0.15172413793103448, + "matched_token_number" : 22 + }, + "00077_00001-00204_00001" : { + "minimal_similarity" : 0.10582010582010581, + "maximum_similarity" : 0.16666666666666666, + "matched_token_number" : 20 + }, + "00125_00001-00184_00002" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.2765957446808511, + "matched_token_number" : 26 + }, + "00125_00001-00184_00003" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.2765957446808511, + "matched_token_number" : 26 + }, + "00138_00001-00154_00002" : { + "minimal_similarity" : 0.07926829268292683, + "maximum_similarity" : 0.09027777777777778, + "matched_token_number" : 13 + }, + "00140_00001-00184_00003" : { + "minimal_similarity" : 0.12030075187969924, + "maximum_similarity" : 0.1702127659574468, + "matched_token_number" : 16 + }, + "00077_00001-00177_00003" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00140_00001-00184_00002" : { + "minimal_similarity" : 0.12030075187969924, + "maximum_similarity" : 0.1702127659574468, + "matched_token_number" : 16 + }, + "00184_00003-00186_00002" : { + "minimal_similarity" : 0.09659090909090909, + "maximum_similarity" : 0.18085106382978725, + "matched_token_number" : 17 + }, + "00153_00001-00194_00001" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00187_00001-00203_00002" : { + "minimal_similarity" : 0.5103448275862069, + "maximum_similarity" : 0.5606060606060606, + "matched_token_number" : 74 + }, + "00113_00002-00131_00005" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.11377245508982035, + "matched_token_number" : 19 + }, + "00121_00001-00200_00002" : { + "minimal_similarity" : 0.05699481865284974, + "maximum_similarity" : 0.06470588235294118, + "matched_token_number" : 11 + }, + "00095_00003-00199_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00002-00129_00008" : { + "minimal_similarity" : 0.031914893617021274, + "maximum_similarity" : 0.0625, + "matched_token_number" : 9 + }, + "00077_00001-00202_00003" : { + "minimal_similarity" : 0.1693121693121693, + "maximum_similarity" : 0.22695035460992907, + "matched_token_number" : 32 + }, + "00005_00002-00135_00001" : { + "minimal_similarity" : 0.09523809523809523, + "maximum_similarity" : 0.09782608695652174, + "matched_token_number" : 18 + }, + "00077_00001-00202_00002" : { + "minimal_similarity" : 0.21693121693121692, + "maximum_similarity" : 0.2907801418439716, + "matched_token_number" : 41 + }, + "00137_00002-00202_00002" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00184_00003-00186_00004" : { + "minimal_similarity" : 0.1388888888888889, + "maximum_similarity" : 0.2127659574468085, + "matched_token_number" : 20 + }, + "00137_00002-00202_00003" : { + "minimal_similarity" : 0.13095238095238096, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00092_00001-00147_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 144 + }, + "00000_00002-00000_00005" : { + "minimal_similarity" : 0.8389261744966443, + "maximum_similarity" : 0.8680555555555556, + "matched_token_number" : 125 + }, + "00000_00002-00000_00003" : { + "minimal_similarity" : 0.972972972972973, + "maximum_similarity" : 1.0, + "matched_token_number" : 144 + }, + "00031_00003-00130_00002" : { + "minimal_similarity" : 0.10526315789473684, + "maximum_similarity" : 0.12280701754385964, + "matched_token_number" : 14 + }, + "00184_00002-00199_00001" : { + "minimal_similarity" : 0.9157894736842105, + "maximum_similarity" : 0.925531914893617, + "matched_token_number" : 87 + }, + "00177_00003-00187_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.17424242424242425, + "matched_token_number" : 23 + }, + "00000_00003-00184_00003" : { + "minimal_similarity" : 0.060810810810810814, + "maximum_similarity" : 0.09574468085106383, + "matched_token_number" : 9 + }, + "00142_00001-00156_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00044_00002-00186_00004" : { + "minimal_similarity" : 0.4027777777777778, + "maximum_similarity" : 0.4264705882352941, + "matched_token_number" : 58 + }, + "00005_00002-00077_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 189 + }, + "00044_00002-00186_00002" : { + "minimal_similarity" : 0.6590909090909091, + "maximum_similarity" : 0.8529411764705882, + "matched_token_number" : 116 + }, + "00142_00001-00156_00003" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00013_00002-00134_00001" : { + "minimal_similarity" : 0.15037593984962405, + "maximum_similarity" : 0.17094017094017094, + "matched_token_number" : 20 + }, + "00195_00001-00201_00001" : { + "minimal_similarity" : 0.12418300653594772, + "maximum_similarity" : 0.14615384615384616, + "matched_token_number" : 19 + }, + "00092_00001-00141_00002" : { + "minimal_similarity" : 0.1, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00000_00003-00184_00002" : { + "minimal_similarity" : 0.060810810810810814, + "maximum_similarity" : 0.09574468085106383, + "matched_token_number" : 9 + }, + "00184_00002-00193_00001" : { + "minimal_similarity" : 0.07272727272727272, + "maximum_similarity" : 0.1276595744680851, + "matched_token_number" : 12 + }, + "00136_00002-00178_00002" : { + "minimal_similarity" : 0.0867579908675799, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00156_00002-00186_00002" : { + "minimal_similarity" : 0.10112359550561797, + "maximum_similarity" : 0.10227272727272728, + "matched_token_number" : 18 + }, + "00000_00005-00005_00002" : { + "minimal_similarity" : 0.047619047619047616, + "maximum_similarity" : 0.06040268456375839, + "matched_token_number" : 9 + }, + "00196_00001-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00147_00001-00195_00001" : { + "minimal_similarity" : 0.11764705882352941, + "maximum_similarity" : 0.125, + "matched_token_number" : 18 + }, + "00147_00001-00195_00002" : { + "minimal_similarity" : 0.11764705882352941, + "maximum_similarity" : 0.125, + "matched_token_number" : 18 + }, + "00155_00001-00194_00001" : { + "minimal_similarity" : 0.3933333333333333, + "maximum_similarity" : 0.472, + "matched_token_number" : 59 + }, + "00156_00002-00186_00004" : { + "minimal_similarity" : 0.1404494382022472, + "maximum_similarity" : 0.1736111111111111, + "matched_token_number" : 25 + }, + "00160_00001-00192_00001" : { + "minimal_similarity" : 0.05806451612903226, + "maximum_similarity" : 0.0661764705882353, + "matched_token_number" : 9 + }, + "00120_00001-00201_00001" : { + "minimal_similarity" : 0.1310344827586207, + "maximum_similarity" : 0.14615384615384616, + "matched_token_number" : 19 + }, + "00160_00001-00192_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00186_00004-00204_00001" : { + "minimal_similarity" : 0.09722222222222222, + "maximum_similarity" : 0.11666666666666667, + "matched_token_number" : 14 + }, + "00133_00001-00186_00002" : { + "minimal_similarity" : 0.1534090909090909, + "maximum_similarity" : 0.16071428571428573, + "matched_token_number" : 27 + }, + "00133_00001-00186_00004" : { + "minimal_similarity" : 0.16666666666666666, + "maximum_similarity" : 0.19444444444444445, + "matched_token_number" : 28 + }, + "00092_00001-00142_00001" : { + "minimal_similarity" : 0.11764705882352941, + "maximum_similarity" : 0.125, + "matched_token_number" : 18 + }, + "00136_00002-00203_00002" : { + "minimal_similarity" : 0.0867579908675799, + "maximum_similarity" : 0.1310344827586207, + "matched_token_number" : 19 + }, + "00000_00003-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00095_00003-00194_00001" : { + "minimal_similarity" : 0.10891089108910891, + "maximum_similarity" : 0.14666666666666667, + "matched_token_number" : 22 + }, + "00138_00001-00156_00002" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.0763888888888889, + "matched_token_number" : 11 + }, + "00138_00001-00156_00003" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.0763888888888889, + "matched_token_number" : 11 + }, + "00196_00001-00202_00003" : { + "minimal_similarity" : 0.024793388429752067, + "maximum_similarity" : 0.06382978723404255, + "matched_token_number" : 9 + }, + "00196_00001-00202_00002" : { + "minimal_similarity" : 0.024793388429752067, + "maximum_similarity" : 0.06382978723404255, + "matched_token_number" : 9 + }, + "00155_00001-00193_00001" : { + "minimal_similarity" : 0.07272727272727272, + "maximum_similarity" : 0.096, + "matched_token_number" : 12 + }, + "00194_00001-00201_00001" : { + "minimal_similarity" : 0.24, + "maximum_similarity" : 0.27692307692307694, + "matched_token_number" : 36 + }, + "00184_00002-00194_00001" : { + "minimal_similarity" : 0.18, + "maximum_similarity" : 0.2872340425531915, + "matched_token_number" : 27 + }, + "00077_00001-00178_00002" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00097_00002-00178_00002" : { + "minimal_similarity" : 0.07738095238095238, + "maximum_similarity" : 0.08783783783783784, + "matched_token_number" : 13 + }, + "00136_00002-00202_00002" : { + "minimal_similarity" : 0.1050228310502283, + "maximum_similarity" : 0.16312056737588654, + "matched_token_number" : 23 + }, + "00134_00001-00184_00003" : { + "minimal_similarity" : 0.23076923076923078, + "maximum_similarity" : 0.2872340425531915, + "matched_token_number" : 27 + }, + "00136_00002-00202_00003" : { + "minimal_similarity" : 0.1461187214611872, + "maximum_similarity" : 0.22695035460992907, + "matched_token_number" : 32 + }, + "00135_00001-00153_00001" : { + "minimal_similarity" : 0.1956521739130435, + "maximum_similarity" : 0.21428571428571427, + "matched_token_number" : 36 + }, + "00186_00004-00203_00002" : { + "minimal_similarity" : 0.2620689655172414, + "maximum_similarity" : 0.2638888888888889, + "matched_token_number" : 38 + }, + "00095_00003-00193_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00120_00001-00142_00001" : { + "minimal_similarity" : 0.9477124183006536, + "maximum_similarity" : 1.0, + "matched_token_number" : 145 + }, + "00147_00001-00194_00001" : { + "minimal_similarity" : 0.1, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00136_00002-00145_00001" : { + "minimal_similarity" : 0.0867579908675799, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00120_00001-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00077_00001-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00134_00001-00184_00002" : { + "minimal_similarity" : 0.23076923076923078, + "maximum_similarity" : 0.2872340425531915, + "matched_token_number" : 27 + }, + "00194_00001-00202_00003" : { + "minimal_similarity" : 0.14666666666666667, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00194_00001-00202_00002" : { + "minimal_similarity" : 0.14666666666666667, + "maximum_similarity" : 0.15602836879432624, + "matched_token_number" : 22 + }, + "00005_00002-00136_00002" : { + "minimal_similarity" : 0.1050228310502283, + "maximum_similarity" : 0.12169312169312169, + "matched_token_number" : 23 + }, + "00155_00001-00199_00001" : { + "minimal_similarity" : 0.08, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 10 + }, + "00005_00002-00130_00002" : { + "minimal_similarity" : 0.06349206349206349, + "maximum_similarity" : 0.09022556390977443, + "matched_token_number" : 12 + }, + "00119_00001-00183_00004" : { + "minimal_similarity" : 0.07333333333333333, + "maximum_similarity" : 0.07482993197278912, + "matched_token_number" : 11 + }, + "00013_00002-00077_00001" : { + "minimal_similarity" : 0.05291005291005291, + "maximum_similarity" : 0.07518796992481203, + "matched_token_number" : 10 + }, + "00160_00001-00193_00001" : { + "minimal_similarity" : 0.06666666666666667, + "maximum_similarity" : 0.08088235294117647, + "matched_token_number" : 11 + }, + "00141_00002-00178_00002" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00031_00002-00177_00003" : { + "minimal_similarity" : 0.06547619047619048, + "maximum_similarity" : 0.08870967741935484, + "matched_token_number" : 11 + }, + "00155_00001-00195_00001" : { + "minimal_similarity" : 0.23529411764705882, + "maximum_similarity" : 0.288, + "matched_token_number" : 36 + }, + "00195_00001-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00136_00002-00201_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00133_00001-00184_00003" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.2765957446808511, + "matched_token_number" : 26 + }, + "00155_00001-00195_00002" : { + "minimal_similarity" : 0.23529411764705882, + "maximum_similarity" : 0.288, + "matched_token_number" : 36 + }, + "00133_00001-00184_00002" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.2765957446808511, + "matched_token_number" : 26 + }, + "00177_00003-00186_00004" : { + "minimal_similarity" : 0.16666666666666666, + "maximum_similarity" : 0.19444444444444445, + "matched_token_number" : 28 + }, + "00000_00002-00195_00002" : { + "minimal_similarity" : 0.12418300653594772, + "maximum_similarity" : 0.13194444444444445, + "matched_token_number" : 19 + }, + "00000_00002-00198_00001" : { + "minimal_similarity" : 0.10101010101010101, + "maximum_similarity" : 0.1388888888888889, + "matched_token_number" : 20 + }, + "00000_00002-00195_00001" : { + "minimal_similarity" : 0.12418300653594772, + "maximum_similarity" : 0.13194444444444445, + "matched_token_number" : 19 + }, + "00120_00001-00141_00002" : { + "minimal_similarity" : 0.31333333333333335, + "maximum_similarity" : 0.32413793103448274, + "matched_token_number" : 47 + }, + "00186_00004-00202_00003" : { + "minimal_similarity" : 0.3194444444444444, + "maximum_similarity" : 0.3262411347517731, + "matched_token_number" : 46 + }, + "00177_00003-00186_00002" : { + "minimal_similarity" : 0.1534090909090909, + "maximum_similarity" : 0.16071428571428573, + "matched_token_number" : 27 + }, + "00186_00004-00202_00002" : { + "minimal_similarity" : 0.2986111111111111, + "maximum_similarity" : 0.3049645390070922, + "matched_token_number" : 43 + }, + "00121_00001-00141_00002" : { + "minimal_similarity" : 0.27461139896373055, + "maximum_similarity" : 0.35333333333333333, + "matched_token_number" : 53 + }, + "00095_00003-00195_00002" : { + "minimal_similarity" : 0.0594059405940594, + "maximum_similarity" : 0.0784313725490196, + "matched_token_number" : 12 + }, + "00095_00003-00195_00001" : { + "minimal_similarity" : 0.0594059405940594, + "maximum_similarity" : 0.0784313725490196, + "matched_token_number" : 12 + }, + "00120_00001-00177_00003" : { + "minimal_similarity" : 0.21428571428571427, + "maximum_similarity" : 0.2482758620689655, + "matched_token_number" : 36 + }, + "00155_00001-00198_00001" : { + "minimal_similarity" : 0.14646464646464646, + "maximum_similarity" : 0.232, + "matched_token_number" : 29 + }, + "00005_00002-00134_00001" : { + "minimal_similarity" : 0.047619047619047616, + "maximum_similarity" : 0.07692307692307693, + "matched_token_number" : 9 + }, + "00195_00001-00203_00002" : { + "minimal_similarity" : 0.1437908496732026, + "maximum_similarity" : 0.15172413793103448, + "matched_token_number" : 22 + }, + "00077_00001-00140_00001" : { + "minimal_similarity" : 0.06349206349206349, + "maximum_similarity" : 0.09022556390977443, + "matched_token_number" : 12 + }, + "00137_00002-00201_00001" : { + "minimal_similarity" : 0.05357142857142857, + "maximum_similarity" : 0.06923076923076923, + "matched_token_number" : 9 + }, + "00092_00001-00145_00001" : { + "minimal_similarity" : 0.08928571428571429, + "maximum_similarity" : 0.10416666666666667, + "matched_token_number" : 15 + }, + "00136_00002-00140_00001" : { + "minimal_similarity" : 0.0502283105022831, + "maximum_similarity" : 0.08270676691729323, + "matched_token_number" : 11 + }, + "00095_00003-00198_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00184_00002-00197_00001" : { + "minimal_similarity" : 0.10606060606060606, + "maximum_similarity" : 0.14893617021276595, + "matched_token_number" : 14 + }, + "00156_00003-00178_00002" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00005_00002-00131_00005" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 189 + }, + "00000_00005-00160_00001" : { + "minimal_similarity" : 0.06711409395973154, + "maximum_similarity" : 0.07352941176470588, + "matched_token_number" : 10 + }, + "00140_00001-00186_00002" : { + "minimal_similarity" : 0.2159090909090909, + "maximum_similarity" : 0.2857142857142857, + "matched_token_number" : 38 + }, + "00121_00001-00202_00003" : { + "minimal_similarity" : 0.16062176165803108, + "maximum_similarity" : 0.2198581560283688, + "matched_token_number" : 31 + }, + "00178_00002-00199_00001" : { + "minimal_similarity" : 0.05952380952380952, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 10 + }, + "00130_00002-00138_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00121_00001-00202_00002" : { + "minimal_similarity" : 0.16062176165803108, + "maximum_similarity" : 0.2198581560283688, + "matched_token_number" : 31 + }, + "00140_00001-00186_00004" : { + "minimal_similarity" : 0.3472222222222222, + "maximum_similarity" : 0.37593984962406013, + "matched_token_number" : 50 + }, + "00177_00003-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00092_00001-00203_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00140_00001-00183_00004" : { + "minimal_similarity" : 0.09523809523809523, + "maximum_similarity" : 0.10526315789473684, + "matched_token_number" : 14 + }, + "00194_00001-00200_00002" : { + "minimal_similarity" : 0.058823529411764705, + "maximum_similarity" : 0.06666666666666667, + "matched_token_number" : 10 + }, + "00137_00002-00145_00001" : { + "minimal_similarity" : 1.0, + "maximum_similarity" : 1.0, + "matched_token_number" : 168 + }, + "00005_00002-00133_00001" : { + "minimal_similarity" : 0.10052910052910052, + "maximum_similarity" : 0.1130952380952381, + "matched_token_number" : 19 + }, + "00013_00002-00137_00002" : { + "minimal_similarity" : 0.18452380952380953, + "maximum_similarity" : 0.23308270676691728, + "matched_token_number" : 31 + }, + "00092_00001-00204_00001" : { + "minimal_similarity" : 0.06944444444444445, + "maximum_similarity" : 0.08333333333333333, + "matched_token_number" : 10 + }, + "00095_00003-00197_00001" : { + "minimal_similarity" : 0.0594059405940594, + "maximum_similarity" : 0.09090909090909091, + "matched_token_number" : 12 + }, + "00195_00001-00202_00003" : { + "minimal_similarity" : 0.06535947712418301, + "maximum_similarity" : 0.07092198581560284, + "matched_token_number" : 10 + }, + "00195_00001-00202_00002" : { + "minimal_similarity" : 0.06535947712418301, + "maximum_similarity" : 0.07092198581560284, + "matched_token_number" : 10 + }, + "00136_00002-00141_00002" : { + "minimal_similarity" : 0.1004566210045662, + "maximum_similarity" : 0.14666666666666667, + "matched_token_number" : 22 + }, + "00155_00001-00197_00001" : { + "minimal_similarity" : 0.12878787878787878, + "maximum_similarity" : 0.136, + "matched_token_number" : 17 + }, + "00177_00003-00184_00002" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.2765957446808511, + "matched_token_number" : 26 + }, + "00134_00001-00186_00002" : { + "minimal_similarity" : 0.1875, + "maximum_similarity" : 0.28205128205128205, + "matched_token_number" : 33 + }, + "00177_00003-00184_00003" : { + "minimal_similarity" : 0.15476190476190477, + "maximum_similarity" : 0.2765957446808511, + "matched_token_number" : 26 + }, + "00000_00002-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00134_00001-00186_00004" : { + "minimal_similarity" : 0.09722222222222222, + "maximum_similarity" : 0.11965811965811966, + "matched_token_number" : 14 + }, + "00156_00002-00187_00001" : { + "minimal_similarity" : 0.05056179775280899, + "maximum_similarity" : 0.06818181818181818, + "matched_token_number" : 9 + }, + "00156_00003-00177_00003" : { + "minimal_similarity" : 0.06179775280898876, + "maximum_similarity" : 0.06547619047619048, + "matched_token_number" : 11 + }, + "00186_00004-00200_00002" : { + "minimal_similarity" : 0.13529411764705881, + "maximum_similarity" : 0.1597222222222222, + "matched_token_number" : 23 + }, + "00121_00001-00201_00001" : { + "minimal_similarity" : 0.046632124352331605, + "maximum_similarity" : 0.06923076923076923, + "matched_token_number" : 9 + }, + "00137_00002-00204_00001" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.19166666666666668, + "matched_token_number" : 23 + }, + "00000_00003-00186_00004" : { + "minimal_similarity" : 0.25, + "maximum_similarity" : 0.2569444444444444, + "matched_token_number" : 37 + }, + "00000_00003-00186_00002" : { + "minimal_similarity" : 0.22727272727272727, + "maximum_similarity" : 0.2702702702702703, + "matched_token_number" : 40 + }, + "00155_00001-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00031_00002-00178_00002" : { + "minimal_similarity" : 0.06547619047619048, + "maximum_similarity" : 0.08870967741935484, + "matched_token_number" : 11 + }, + "00013_00002-00138_00001" : { + "minimal_similarity" : 0.06944444444444445, + "maximum_similarity" : 0.07518796992481203, + "matched_token_number" : 10 + }, + "00136_00002-00200_00002" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00141_00002-00177_00003" : { + "minimal_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00184_00003-00187_00001" : { + "minimal_similarity" : 0.10606060606060606, + "maximum_similarity" : 0.14893617021276595, + "matched_token_number" : 14 + }, + "00014_00001-00113_00002" : { + "minimal_similarity" : 0.2634730538922156, + "maximum_similarity" : 0.29333333333333333, + "matched_token_number" : 44 + }, + "00137_00002-00203_00002" : { + "minimal_similarity" : 0.13690476190476192, + "maximum_similarity" : 0.15862068965517243, + "matched_token_number" : 23 + }, + "00184_00002-00198_00001" : { + "minimal_similarity" : 0.045454545454545456, + "maximum_similarity" : 0.09574468085106383, + "matched_token_number" : 9 + }, + "00202_00003-00203_00002" : { + "minimal_similarity" : 0.33793103448275863, + "maximum_similarity" : 0.3475177304964539, + "matched_token_number" : 49 + }, + "00134_00001-00187_00001" : { + "minimal_similarity" : 0.08333333333333333, + "maximum_similarity" : 0.09401709401709402, + "matched_token_number" : 11 + }, + "00095_00003-00196_00001" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00133_00001-00183_00004" : { + "minimal_similarity" : 0.0, + "maximum_similarity" : 0.0, + "matched_token_number" : 0 + }, + "00000_00002-00197_00001" : { + "minimal_similarity" : 0.20833333333333334, + "maximum_similarity" : 0.22727272727272727, + "matched_token_number" : 30 + }, + "00121_00001-00142_00001" : { + "minimal_similarity" : 0.17098445595854922, + "maximum_similarity" : 0.21568627450980393, + "matched_token_number" : 33 + }, + "00044_00002-00119_00001" : { + "minimal_similarity" : 0.18, + "maximum_similarity" : 0.19852941176470587, + "matched_token_number" : 27 + } + }, + "identifier" : "MTM: 9", + "goldStandard" : { + "matchAverage" : 0.9691523648180836, + "nonMatchAverage" : 0.1309958405783095 + } +} ] \ No newline at end of file diff --git a/endtoend-testing/src/test/resources/results/java/sortAlgo.json b/endtoend-testing/src/test/resources/results/sortAlgo.json similarity index 72% rename from endtoend-testing/src/test/resources/results/java/sortAlgo.json rename to endtoend-testing/src/test/resources/results/sortAlgo.json index 80fab2e72..392147633 100644 --- a/endtoend-testing/src/test/resources/results/java/sortAlgo.json +++ b/endtoend-testing/src/test/resources/results/sortAlgo.json @@ -1,15 +1,12 @@ [ { - "options" : { - "minimum_token_match" : 3 - }, "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 +16,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 +31,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 +61,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 +91,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 +121,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 +166,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 +176,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 +191,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 +256,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 +291,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 +301,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 +340,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 +355,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 +416,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,44 +426,44 @@ "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, "maximum_similarity" : 0.8604651162790697, "matched_token_number" : 37 }, - "SortAlgo3_6-SortAlgo5" : { - "minimal_similarity" : 0.4, - "maximum_similarity" : 0.5116279069767442, - "matched_token_number" : 22 - }, "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-SortAlgo5" : { + "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 +471,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 +496,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 +506,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 +526,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 - }, - "SortAlgo2_5-SortAlgo7" : { - "minimal_similarity" : 0.3392857142857143, - "maximum_similarity" : 0.4418604651162791, - "matched_token_number" : 19 + "minimal_similarity" : 0.5510204081632653, + "maximum_similarity" : 0.627906976744186, + "matched_token_number" : 27 }, "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 + }, + "SortAlgo2_5-SortAlgo7" : { + "minimal_similarity" : 0.375, + "maximum_similarity" : 0.4883720930232558, + "matched_token_number" : 21 }, "SortAlgo1-SortAlgo4d3" : { "minimal_similarity" : 0.8297872340425532, @@ -579,9 +576,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 +595,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 +646,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 +656,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 +711,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 +751,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,23 +851,22 @@ "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 } - } -}, { - "options" : { - "minimum_token_match" : 9 }, + "identifier" : "MTM: 3", + "goldStandard" : null +}, { "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 +876,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 +892,7 @@ }, "SortAlgo1_3-SortAlgo6" : { "minimal_similarity" : 0.3103448275862069, - "maximum_similarity" : 0.375, + "maximum_similarity" : 0.3673469387755102, "matched_token_number" : 18 }, "SortAlgo-SortAlgo1" : { @@ -930,19 +926,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 +957,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 +981,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 +1011,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 +1036,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 +1052,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 +1091,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 +1126,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 +1152,7 @@ }, "SortAlgo1_6-SortAlgo4d1" : { "minimal_similarity" : 0.3541666666666667, - "maximum_similarity" : 0.40476190476190477, + "maximum_similarity" : 0.3953488372093023, "matched_token_number" : 17 }, "SortAlgo4d2-SortAlgo7" : { @@ -1166,7 +1162,7 @@ }, "SortAlgo1_6-SortAlgo4d2" : { "minimal_similarity" : 0.3469387755102041, - "maximum_similarity" : 0.40476190476190477, + "maximum_similarity" : 0.3953488372093023, "matched_token_number" : 17 }, "SortAlgo4d2-SortAlgo5" : { @@ -1176,12 +1172,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 +1206,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 +1216,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 +1232,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 +1242,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 +1276,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,42 +1286,42 @@ "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, "maximum_similarity" : 0.6976744186046512, "matched_token_number" : 30 }, - "SortAlgo3_6-SortAlgo5" : { + "SortAlgo2_5-SortAlgo3_6" : { "minimal_similarity" : 0.0, "maximum_similarity" : 0.0, "matched_token_number" : 0 }, - "SortAlgo2_5-SortAlgo3_6" : { + "SortAlgo3_6-SortAlgo5" : { "minimal_similarity" : 0.0, "maximum_similarity" : 0.0, "matched_token_number" : 0 }, "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 +1336,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 +1356,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 +1371,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 +1386,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" : { @@ -1424,15 +1420,15 @@ "maximum_similarity" : 0.0, "matched_token_number" : 0 }, - "SortAlgo2_5-SortAlgo7" : { - "minimal_similarity" : 0.17857142857142858, - "maximum_similarity" : 0.23255813953488372, - "matched_token_number" : 10 - }, "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 + }, + "SortAlgo2_5-SortAlgo7" : { + "minimal_similarity" : 0.19642857142857142, + "maximum_similarity" : 0.2558139534883721, + "matched_token_number" : 11 }, "SortAlgo1-SortAlgo4d3" : { "minimal_similarity" : 0.6595744680851063, @@ -1441,7 +1437,7 @@ }, "SortAlgo1_5-SortAlgo4" : { "minimal_similarity" : 0.2558139534883721, - "maximum_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.2558139534883721, "matched_token_number" : 11 }, "SortAlgo1_5-SortAlgo5" : { @@ -1460,21 +1456,21 @@ "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" : { + "SortAlgo1_5-SortAlgo3" : { "minimal_similarity" : 0.0, "maximum_similarity" : 0.0, "matched_token_number" : 0 }, - "SortAlgo1_5-SortAlgo3" : { + "SortAlgo3_5-SortAlgo7" : { "minimal_similarity" : 0.0, "maximum_similarity" : 0.0, "matched_token_number" : 0 @@ -1510,12 +1506,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 +1521,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,7 +1577,7 @@ }, "SortAlgo2_5-SortAlgo4" : { "minimal_similarity" : 0.2558139534883721, - "maximum_similarity" : 0.2619047619047619, + "maximum_similarity" : 0.2558139534883721, "matched_token_number" : 11 }, "SortAlgo2_5-SortAlgo3" : { @@ -1615,17 +1611,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 +1637,7 @@ }, "SortAlgo3-SortAlgo6" : { "minimal_similarity" : 0.5370370370370371, - "maximum_similarity" : 0.6041666666666666, + "maximum_similarity" : 0.5918367346938775, "matched_token_number" : 29 }, "SortAlgo2_5-SortAlgo4d2" : { @@ -1650,9 +1646,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 +1656,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 +1672,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 +1682,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,8 +1712,10 @@ }, "SortAlgo1_2-SortAlgo1_4" : { "minimal_similarity" : 0.41818181818181815, - "maximum_similarity" : 0.5476190476190477, + "maximum_similarity" : 0.5348837209302325, "matched_token_number" : 23 } - } + }, + "identifier" : "MTM: 9", + "goldStandard" : null } ] \ No newline at end of file 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..6697788a5 --- /dev/null +++ b/language-antlr-utils/pom.xml @@ -0,0 +1,70 @@ + + + 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 + + + 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..1d75847bd --- /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, boolean normalize) throws ParsingException { + if (this.parser == null) { + this.parser = this.initializeParser(normalize); + } + + 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(boolean normalize) { + 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..cf81a3718 --- /dev/null +++ b/language-antlr-utils/src/main/java/de/jplag/antlr/AbstractAntlrListener.java @@ -0,0 +1,165 @@ +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(); + if (next.children != null) { + 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..7fd76966b --- /dev/null +++ b/language-antlr-utils/src/main/java/de/jplag/antlr/AbstractAntlrParserAdapter.java @@ -0,0 +1,102 @@ +package de.jplag.antlr; + +import java.io.File; +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 (Exception exception) { // catching generic exception to capture any exceptions thrown by ANTLR. + 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..0ec4c19af --- /dev/null +++ b/language-antlr-utils/src/main/java/de/jplag/antlr/AbstractVisitor.java @@ -0,0 +1,133 @@ +package de.jplag.antlr; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; + +import org.antlr.v4.runtime.Token; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +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 static final Logger logger = LoggerFactory.getLogger(AbstractVisitor.class); + + 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) { + withSemantics(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) { + if (entryTokenType == null && entrySemantics != null) { + logger.warn("Received semantics, but no token type, so no token was generated and the semantics discarded"); + } + addToken(data, entryTokenType, entrySemantics, this::extractEnterToken); // addToken takes null token types + 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..96436248d --- /dev/null +++ b/language-antlr-utils/src/main/java/de/jplag/antlr/ContextVisitor.java @@ -0,0 +1,143 @@ +package de.jplag.antlr; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; + +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 exitTokenType; + 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) { + exitTokenType = 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) { + withSemantics(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, exitTokenType, exitSemantics, ParserRuleContext::getStop); + exitHandlers.forEach(handler -> handler.accept(data)); + } + + @Override + 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..5d2a8e51a --- /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; + private 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..80fa407f9 --- /dev/null +++ b/language-antlr-utils/src/main/java/de/jplag/antlr/TerminalVisitor.java @@ -0,0 +1,20 @@ +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); + } + + @Override + 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..150088a92 --- /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 org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +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 = LoggerFactory.getLogger(TokenCollector.class); + + 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) { + 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.warn("Received semantics for token {} 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..b8fe50f51 --- /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, false)); + } + + @Test + void testLanguageWithStaticParser() throws ParsingException { + TestLanguage lang = new TestLanguage(); + Assertions.assertEquals(0, lang.parse(Set.of(), false).size()); + } + + @Test + void testLanguageWithLazyParser() throws ParsingException { + LanguageWithLazyParser lang = new LanguageWithLazyParser(); + Assertions.assertEquals(0, lang.parse(Set.of(), false).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(boolean normalize) { + 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..6538dc40c --- /dev/null +++ b/language-antlr-utils/src/test/java/de/jplag/antlr/ParserTest.java @@ -0,0 +1,33 @@ +package de.jplag.antlr; + +import static de.jplag.antlr.testLanguage.TestTokenType.ADDITION; +import static de.jplag.antlr.testLanguage.TestTokenType.NUMBER; +import static de.jplag.antlr.testLanguage.TestTokenType.SUBTRACTION; +import static de.jplag.antlr.testLanguage.TestTokenType.SUB_EXPRESSION_BEGIN; +import static de.jplag.antlr.testLanguage.TestTokenType.SUB_EXPRESSION_END; + +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..c61ec4c3c --- /dev/null +++ b/language-antlr-utils/src/test/java/de/jplag/antlr/testLanguage/TestListener.java @@ -0,0 +1,30 @@ +package de.jplag.antlr.testLanguage; + +import static de.jplag.antlr.testLanguage.TestTokenType.ADDITION; +import static de.jplag.antlr.testLanguage.TestTokenType.NUMBER; +import static de.jplag.antlr.testLanguage.TestTokenType.SUBTRACTION; +import static de.jplag.antlr.testLanguage.TestTokenType.SUB_EXPRESSION_BEGIN; +import static de.jplag.antlr.testLanguage.TestTokenType.SUB_EXPRESSION_END; +import static de.jplag.antlr.testLanguage.TestTokenType.VARDEF; + +import de.jplag.antlr.AbstractAntlrListener; +import de.jplag.antlr.TestParser; +import de.jplag.antlr.TestParser.CalcExpressionContext; +import de.jplag.antlr.TestParser.OperatorContext; +import de.jplag.antlr.TestParser.SubExpressionContext; +import de.jplag.antlr.TestParser.VarDefContext; +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..985477250 --- /dev/null +++ b/language-antlr-utils/src/test/java/de/jplag/antlr/testLanguage/TestParserAdapter.java @@ -0,0 +1,35 @@ +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.AbstractAntlrListener; +import de.jplag.antlr.AbstractAntlrParserAdapter; +import de.jplag.antlr.TestLexer; +import de.jplag.antlr.TestParser; + +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..99d1d2e03 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 + 74.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..ffe6aa9a6 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. */ @@ -30,12 +32,33 @@ public interface Language { int minimumTokenMatch(); /** - * Parses a set of files. + * Parses a set of files. Override this method, if you don't require normalization. * @param files are the files to parse. * @return the list of parsed JPlag tokens. * @throws ParsingException if an error during parsing the files occurred. + * @deprecated Replaced by {@link #parse(Set, boolean)} + */ + @Deprecated(forRemoval = true) + default List parse(Set files) throws ParsingException { + return parse(files, false); + } + + /** + * Parses a set of files. Override this method, if you require normalization within the language module. + * @param files are the files to parse. + * @param normalize True, if the tokens should be normalized + * @return the list of parsed JPlag tokens. + * @throws ParsingException if an error during parsing the files occurred. + */ + List parse(Set files, boolean normalize) 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. */ - List parse(Set files) throws ParsingException; + default boolean tokensHaveSemantics() { + return false; + } /** * Determines whether a fixed-width font should be used to display that language. @@ -58,4 +81,45 @@ 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; + } + + /** + * @return True, if this language supports token sequence normalization. This does not include other normalization + * mechanisms that might be part of the language modules. + */ + default boolean supportsNormalization() { + return false; + } + + /** + * Override this method, if you need normalization within the language module, but not in the core module. + * @return True, If the core normalization should be used. + */ + default boolean requiresCoreNormalization() { + return true; + } } diff --git a/language-api/src/main/java/de/jplag/ParsingException.java b/language-api/src/main/java/de/jplag/ParsingException.java index 4f83721b4..c6e1ad627 100644 --- a/language-api/src/main/java/de/jplag/ParsingException.java +++ b/language-api/src/main/java/de/jplag/ParsingException.java @@ -60,16 +60,14 @@ public ParsingException(File file, String reason, Throwable cause) { * the provided exception if only one was provided. */ public static ParsingException wrappingExceptions(Collection exceptions) { - switch (exceptions.size()) { - case 0: - return null; - case 1: - return exceptions.iterator().next(); - default: { + return switch (exceptions.size()) { + case 0 -> null; + case 1 -> exceptions.iterator().next(); + default -> { String message = exceptions.stream().map(ParsingException::getMessage).collect(Collectors.joining("\n")); - return new ParsingException(message); + yield new ParsingException(message); } - } + }; } private ParsingException(String message) { @@ -78,9 +76,11 @@ private ParsingException(String message) { private static String constructMessage(File file, String reason) { StringBuilder messageBuilder = new StringBuilder(); - messageBuilder.append("failed to parse '%s'".formatted(file)); + if (reason == null || !reason.contains(file.toString())) { + messageBuilder.append("failed to parse '%s'".formatted(file)); + } if (reason != null && !reason.isBlank()) { - messageBuilder.append(" with reason: %s".formatted(reason)); + messageBuilder.append(reason); } return messageBuilder.toString(); } 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..d4ac238b6 100644 --- a/language-api/src/main/java/de/jplag/Token.java +++ b/language-api/src/main/java/de/jplag/Token.java @@ -5,29 +5,24 @@ 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. * The language parsers decide what is a token and what is not. */ public class Token { - private Logger logger = LoggerFactory.getLogger(this.getClass()); + private final Logger logger = LoggerFactory.getLogger(this.getClass()); /** Indicates that the requested field has no value. */ public static final int NO_VALUE = -1; - private int line; - private int column; - 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 final int line; + private final int column; + private final int length; + private final File file; + private final TokenType type; + 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..1581beb02 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 -> { @@ -211,8 +224,9 @@ private void resetLinePosition() { public PrinterOutputBuilder append(String str) { // Avoid too many blank lines trailingLineSeparators = str.equals(LINE_SEPARATOR) ? trailingLineSeparators + 1 : 0; - if (trailingLineSeparators >= 3) + if (trailingLineSeparators >= 3) { return this; + } builder.append(str); columnIndex += str.length(); 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..2eb99262d --- /dev/null +++ b/language-api/src/main/java/de/jplag/semantics/CodeSemantics.java @@ -0,0 +1,216 @@ +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 final Set reads; + private final 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..b187db34c --- /dev/null +++ b/language-api/src/main/java/de/jplag/semantics/VariableRegistry.java @@ -0,0 +1,186 @@ +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; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Registry of variables to assist in generating token semantics. + */ +public class VariableRegistry { + private static final Logger logger = LoggerFactory.getLogger(VariableRegistry.class); + + private CodeSemantics semantics; + private final Map fileVariables; + private final Deque> classVariables; // map class name to map of variable names to variables + private final Map> localVariables; // map local variable name to stack of variables + private final 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) { + logger.debug("Register variable {}", variableName); + 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) { + logger.debug("{} {}", variableName, nextVariableAccessType); + 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()); + if (!classVariables.isEmpty()) { + 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..5ce3c62b6 --- /dev/null +++ b/language-api/src/main/java/de/jplag/util/FileUtils.java @@ -0,0 +1,181 @@ +package de.jplag.util; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.Writer; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +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 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..37b8338cd --- /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 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 org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +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 logger = LoggerFactory.getLogger(this.getClass()); + + 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); + logger.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..2e917fd92 --- /dev/null +++ b/language-testutils/src/test/java/de/jplag/testutils/datacollector/FileTestData.java @@ -0,0 +1,60 @@ +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..196d5cb2a --- /dev/null +++ b/language-testutils/src/test/java/de/jplag/testutils/datacollector/TestDataCollector.java @@ -0,0 +1,189 @@ +package de.jplag.testutils.datacollector; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Set; +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..2f6dcea47 --- /dev/null +++ b/language-testutils/src/test/java/de/jplag/testutils/datacollector/TestSourceIgnoredLinesCollector.java @@ -0,0 +1,81 @@ +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)); + } + + /** + * Ignores lines that match the given regular expression. Whitespaces to the left and right of the line will be trimmed + * first. + * @param regex The regular expression + */ + public void ignoreLinesByRegex(String regex) { + this.ignoreByCondition(line -> line.trim().matches(regex)); + } + + 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.originalSource.length; 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/c/README.md b/languages/c/README.md new file mode 100644 index 000000000..735466e44 --- /dev/null +++ b/languages/c/README.md @@ -0,0 +1,12 @@ +# JPlag C language module + +This module allows the use of JPlag with submissions in c. + +## Usage + +To parse C submissions run JPlag with: ` c` or use the `-l c` options. +To use the module from the API configure your `JPlagOption` object with `new CLanguage()` as 'Language' as described in the usage information in the [readme](https://github.com/jplag/JPlag#usage) and [in the wiki](https://github.com/jplag/JPlag/wiki/1.-How-to-Use-JPlag). + +## C++ + +This module might work with C++ submissions. However you should use the [cpp module](https://github.com/jplag/JPlag/tree/main/languages/cpp) for that. \ No newline at end of file diff --git a/languages/c/pom.xml b/languages/c/pom.xml new file mode 100644 index 000000000..71d9cdb8e --- /dev/null +++ b/languages/c/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + + de.jplag + languages + ${revision} + + c + + + + + com.helger.maven + ph-javacc-maven-plugin + + + javacc-gen + + javacc + + generate-sources + + 21 + true + de.jplag.c + src/main/javacc + ${project.build.directory}/generated-sources/javacc + + + + + + + diff --git a/languages/cpp/src/main/java/de/jplag/cpp/Language.java b/languages/c/src/main/java/de/jplag/c/CLanguage.java similarity index 67% rename from languages/cpp/src/main/java/de/jplag/cpp/Language.java rename to languages/c/src/main/java/de/jplag/c/CLanguage.java index dcc69edd7..ba99dbf49 100644 --- a/languages/cpp/src/main/java/de/jplag/cpp/Language.java +++ b/languages/c/src/main/java/de/jplag/c/CLanguage.java @@ -1,4 +1,4 @@ -package de.jplag.cpp; +package de.jplag.c; import java.io.File; import java.util.List; @@ -6,16 +6,17 @@ import org.kohsuke.MetaInfServices; +import de.jplag.Language; import de.jplag.ParsingException; import de.jplag.Token; @MetaInfServices(de.jplag.Language.class) -public class Language implements de.jplag.Language { - private static final String IDENTIFIER = "cpp"; +public class CLanguage implements Language { + private static final String IDENTIFIER = "c"; - private final Scanner scanner; // cpp code is scanned not parsed + private final Scanner scanner; // c code is scanned not parsed - public Language() { + public CLanguage() { scanner = new Scanner(); } @@ -26,7 +27,7 @@ public String[] suffixes() { @Override public String getName() { - return "C/C++ Scanner [basic markup]"; + return "C Scanner"; } @Override @@ -40,7 +41,7 @@ public int minimumTokenMatch() { } @Override - public List parse(Set files) throws ParsingException { + public List parse(Set files, boolean normalize) throws ParsingException { return this.scanner.scan(files); } } diff --git a/languages/c/src/main/java/de/jplag/c/CTokenType.java b/languages/c/src/main/java/de/jplag/c/CTokenType.java new file mode 100644 index 000000000..185daa3e1 --- /dev/null +++ b/languages/c/src/main/java/de/jplag/c/CTokenType.java @@ -0,0 +1,77 @@ +package de.jplag.c; + +import de.jplag.TokenType; + +public enum CTokenType implements TokenType { + C_BLOCK_BEGIN("BLOCK{"), + C_BLOCK_END("}BLOCK"), + C_QUESTIONMARK("COND"), + C_ELLIPSIS("..."), + C_ASSIGN("ASSIGN"), + C_DOT("DOT"), + C_ARROW("ARROW"), + C_ARROWSTAR("ARROWSTAR"), + C_AUTO("AUTO"), + C_BREAK("BREAK"), + C_CASE("CASE"), + C_CATCH("CATCH"), + C_CHAR("CHAR"), + C_CONST("CONST"), + C_CONTINUE("CONTINUE"), + C_DEFAULT("DEFAULT"), + C_DELETE("DELETE"), + C_DO("DO"), + C_DOUBLE("DOUBLE"), + C_ELSE("ELSE"), + C_ENUM("ENUM"), + C_EXTERN("EXTERN"), + C_FLOAT("FLOAT"), + C_FOR("FOR"), + C_FRIEND("FRIEND"), + C_GOTO("GOTO"), + C_IF("IF"), + C_INLINE("INLINE"), + C_INT("INT"), + C_LONG("LONG"), + C_NEW("NEW"), + C_PRIVATE("PRIVATE"), + C_PROTECTED("PROTECTED"), + C_PUBLIC("PUBLIC"), + C_REDECLARED("REDECLARED"), + C_REGISTER("REGISTER"), + C_RETURN("RETURN"), + C_SHORT("SHORT"), + C_SIGNED("SIGNED"), + C_SIZEOF("SIZEOF"), + C_STATIC("STATIC"), + C_STRUCT("STRUCT"), + C_CLASS("CLASS"), + C_SWITCH("SWITCH"), + C_TEMPLATE("TEMPLATE"), + C_THIS("THIS"), + C_TRY("TRY"), + C_TYPEDEF("TYPEDEF"), + C_UNION("UNION"), + C_UNSIGNED("UNSIGNED"), + C_VIRTUAL("VIRTUAL"), + C_VOID("VOID"), + C_VOLATILE("VOLATILE"), + C_WHILE("WHILE"), + C_OPERATOR("OPERATOR"), + C_THROW("THROW"), + C_ID("ID"), + C_FUN("FUN"), + C_DOTSTAR("DOTSTAR"), + C_NULL("NULL"); + + private final String description; + + @Override + public String getDescription() { + return this.description; + } + + CTokenType(String description) { + this.description = description; + } +} diff --git a/languages/cpp/src/main/java/de/jplag/cpp/NewlineStream.java b/languages/c/src/main/java/de/jplag/c/NewlineStream.java similarity index 97% rename from languages/cpp/src/main/java/de/jplag/cpp/NewlineStream.java rename to languages/c/src/main/java/de/jplag/c/NewlineStream.java index 9cc21a3d8..f45c9af61 100644 --- a/languages/cpp/src/main/java/de/jplag/cpp/NewlineStream.java +++ b/languages/c/src/main/java/de/jplag/c/NewlineStream.java @@ -1,4 +1,4 @@ -package de.jplag.cpp; +package de.jplag.c; import java.io.IOException; import java.io.InputStream; diff --git a/languages/cpp/src/main/java/de/jplag/cpp/Scanner.java b/languages/c/src/main/java/de/jplag/c/Scanner.java similarity index 91% rename from languages/cpp/src/main/java/de/jplag/cpp/Scanner.java rename to languages/c/src/main/java/de/jplag/c/Scanner.java index e7f25476d..c3292814e 100644 --- a/languages/cpp/src/main/java/de/jplag/cpp/Scanner.java +++ b/languages/c/src/main/java/de/jplag/c/Scanner.java @@ -1,4 +1,4 @@ -package de.jplag.cpp; +package de.jplag.c; import java.io.File; import java.util.ArrayList; @@ -32,7 +32,7 @@ public List scan(Set files) throws ParsingException { return tokens; } - public void add(CPPTokenType type, de.jplag.cpp.Token token) { + public void add(CTokenType type, de.jplag.c.Token token) { int length = token.endColumn - token.beginColumn + 1; tokens.add(new Token(type, currentFile, token.beginLine, token.beginColumn, length)); } diff --git a/languages/cpp/src/main/java/de/jplag/cpp/experimental/GCCSourceAnalysis.java b/languages/c/src/main/java/de/jplag/c/experimental/GCCSourceAnalysis.java similarity index 90% rename from languages/cpp/src/main/java/de/jplag/cpp/experimental/GCCSourceAnalysis.java rename to languages/c/src/main/java/de/jplag/c/experimental/GCCSourceAnalysis.java index 4b9371ff3..d78aceb7a 100644 --- a/languages/cpp/src/main/java/de/jplag/cpp/experimental/GCCSourceAnalysis.java +++ b/languages/c/src/main/java/de/jplag/c/experimental/GCCSourceAnalysis.java @@ -1,10 +1,14 @@ -package de.jplag.cpp.experimental; +package de.jplag.c.experimental; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,7 +28,8 @@ public GCCSourceAnalysis() { this.logger = LoggerFactory.getLogger(this.getClass()); } - public boolean isTokenIgnored(de.jplag.cpp.Token token, File file) { + @Override + public boolean isTokenIgnored(de.jplag.c.Token token, File file) { String fileName = file.getName(); if (linesToDelete.containsKey(fileName)) { var ignoredLineNumbers = linesToDelete.get(fileName); @@ -33,6 +38,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/cpp/src/main/java/de/jplag/cpp/experimental/SourceAnalysis.java b/languages/c/src/main/java/de/jplag/c/experimental/SourceAnalysis.java similarity index 90% rename from languages/cpp/src/main/java/de/jplag/cpp/experimental/SourceAnalysis.java rename to languages/c/src/main/java/de/jplag/c/experimental/SourceAnalysis.java index 0d846370e..f92986d1d 100644 --- a/languages/cpp/src/main/java/de/jplag/cpp/experimental/SourceAnalysis.java +++ b/languages/c/src/main/java/de/jplag/c/experimental/SourceAnalysis.java @@ -1,4 +1,4 @@ -package de.jplag.cpp.experimental; +package de.jplag.c.experimental; import java.io.File; import java.util.Set; @@ -16,7 +16,7 @@ public interface SourceAnalysis { * @param file The file the token was scanned in * @return True, if the token should not be added to a TokenList, false if it should */ - boolean isTokenIgnored(de.jplag.cpp.Token token, File file); + boolean isTokenIgnored(de.jplag.c.Token token, File file); /** * Executes the source analysis on the files of a submission. diff --git a/languages/cpp/src/main/java/de/jplag/cpp/experimental/UnreachableCodeFilter.java b/languages/c/src/main/java/de/jplag/c/experimental/UnreachableCodeFilter.java similarity index 89% rename from languages/cpp/src/main/java/de/jplag/cpp/experimental/UnreachableCodeFilter.java rename to languages/c/src/main/java/de/jplag/c/experimental/UnreachableCodeFilter.java index e795c6976..e325c914b 100644 --- a/languages/cpp/src/main/java/de/jplag/cpp/experimental/UnreachableCodeFilter.java +++ b/languages/c/src/main/java/de/jplag/c/experimental/UnreachableCodeFilter.java @@ -1,7 +1,17 @@ -package de.jplag.cpp.experimental; +package de.jplag.c.experimental; import static de.jplag.SharedTokenType.FILE_END; -import static de.jplag.cpp.CPPTokenType.*; +import static de.jplag.c.CTokenType.C_BLOCK_BEGIN; +import static de.jplag.c.CTokenType.C_BLOCK_END; +import static de.jplag.c.CTokenType.C_BREAK; +import static de.jplag.c.CTokenType.C_CASE; +import static de.jplag.c.CTokenType.C_CONTINUE; +import static de.jplag.c.CTokenType.C_FOR; +import static de.jplag.c.CTokenType.C_GOTO; +import static de.jplag.c.CTokenType.C_IF; +import static de.jplag.c.CTokenType.C_RETURN; +import static de.jplag.c.CTokenType.C_THROW; +import static de.jplag.c.CTokenType.C_WHILE; import java.util.List; import java.util.ListIterator; diff --git a/languages/cpp/src/main/javacc/CPP.jj b/languages/c/src/main/javacc/CPP.jj similarity index 84% rename from languages/cpp/src/main/javacc/CPP.jj rename to languages/c/src/main/javacc/CPP.jj index 678c1c20c..ee4ca34d8 100644 --- a/languages/cpp/src/main/javacc/CPP.jj +++ b/languages/c/src/main/javacc/CPP.jj @@ -9,10 +9,12 @@ options DEBUG_PARSER = false; DEBUG_LOOKAHEAD = false; DEBUG_TOKEN_MANAGER = false; + UNICODE_INPUT = true; + JAVA_UNICODE_ESCAPE = true; } PARSER_BEGIN(CPPScanner) -package de.jplag.cpp; +package de.jplag.c; import java.io.File; import java.io.FileInputStream; @@ -21,7 +23,7 @@ import java.io.InputStream; import de.jplag.ParsingException; -import static de.jplag.cpp.CPPTokenType.*; +import static de.jplag.c.CTokenType.*; public class CPPScanner { private Scanner delegatingScanner; @@ -264,7 +266,38 @@ TOKEN : TOKEN : { - < ID : ["a"-"z","A"-"Z", "_"] (["a"-"z","A"-"Z","0"-"9","_"])* > + < ID : ( + ["a"-"z","A"-"Z", "_"] + | ["\u00A8", "\u00AA", "\u00AD", "\u00AF", "\u00B2"-"\u00B5", "\u00B7"-"\u00BA", "\u00BC"-"\u00BE", "\u00C0"-"\u00D6", + "\u00D8"-"\u00F6", "\u00F8"-"\u00FF"] + | ["\u0100"-"\u167F", "\u1681"-"\u180D", "\u180F"-"\u1FFF"] + | ["\u200B"-"\u200D", "\u202A"-"\u202E", "\u203F"-"\u2040", "\u2054", "\u2060"-"\u206F"] + | ["\u2070"-"\u218F", "\u2460"-"\u24FF", "\u2776"-"\u2793", "\u2C00"-"\u2DFF", "\u2E80"-"\u2FFF"] + | ["\u3004"-"\u3007", "\u3021"-"\u302F", "\u3031"-"\u303F"] + | ["\u3040"-"\uD7FF"] + | ["\uF900"-"\uFD3D", "\uFD40"-"\uFDCF", "\uFDF0"-"\uFE44", "\uFE47"-"\uFFFD"] + /* unsupported by javacc + | ["\u10000"-"\u1FFFD", "\u20000"-"\u2FFFD", "\u30000"-"\u3FFFD", "\u40000"-"\u4FFFD", "\u50000"-"\u5FFFD", + "\u60000"-"\u6FFFD", "\u70000"-"\u7FFFD", "\u80000"-"\u8FFFD", "\u90000"-"\u9FFFD", "\uA0000"-"\uAFFFD", + "\uB0000"-"\uBFFFD", "\uC0000"-"\uCFFFD", "\uD0000"-"\uDFFFD", "\uE0000"-"\uEFFFD"] + */ + ) + ( + ["a"-"z","A"-"Z","0"-"9","_"] + | ["\u00A8", "\u00AA", "\u00AD", "\u00AF", "\u00B2"-"\u00B5", "\u00B7"-"\u00BA", "\u00BC"-"\u00BE", "\u00C0"-"\u00D6", + "\u00D8"-"\u00F6", "\u00F8"-"\u00FF"] + | ["\u0100"-"\u167F", "\u1681"-"\u180D", "\u180F"-"\u1FFF"] + | ["\u200B"-"\u200D", "\u202A"-"\u202E", "\u203F"-"\u2040", "\u2054", "\u2060"-"\u206F"] + | ["\u2070"-"\u218F", "\u2460"-"\u24FF", "\u2776"-"\u2793", "\u2C00"-"\u2DFF", "\u2E80"-"\u2FFF"] + | ["\u3004"-"\u3007", "\u3021"-"\u302F", "\u3031"-"\u303F"] + | ["\u3040"-"\uD7FF"] + | ["\uF900"-"\uFD3D", "\uFD40"-"\uFDCF", "\uFDF0"-"\uFE44", "\uFE47"-"\uFFFD"] + /* unsupported by javacc + | ["\u10000"-"\u1FFFD", "\u20000"-"\u2FFFD", "\u30000"-"\u3FFFD", "\u40000"-"\u4FFFD", "\u50000"-"\u5FFFD", + "\u60000"-"\u6FFFD", "\u70000"-"\u7FFFD", "\u80000"-"\u8FFFD", "\u90000"-"\u9FFFD", "\uA0000"-"\uAFFFD", + "\uB0000"-"\uBFFFD", "\uC0000"-"\uCFFFD", "\uD0000"-"\uDFFFD", "\uE0000"-"\uEFFFD"] + */ + )* > } diff --git a/languages/cpp2/README.md b/languages/cpp/README.md similarity index 55% rename from languages/cpp2/README.md rename to languages/cpp/README.md index 935b1b358..9eb9b09aa 100644 --- a/languages/cpp2/README.md +++ b/languages/cpp/README.md @@ -1,11 +1,8 @@ # JPlag C++ language module -**Note**: This language module is meant to replace the existing C++ language module in the future. -While the old language module is based on lexer tokens, this language module uses a parse tree for token extraction. -The base package name of this language module and its identifier are `cpp2` currently, but this might change if the old -language module gets replaced. +**Note**: This replaces the old cpp module, which is now only meant for c, as it works better for c than this one. -The JPlag C++ frontend allows the use of JPlag with submissions in C/C++.
+The JPlag C++ frontend allows the use of JPlag with submissions in C++.
It is based on the [C++ ANTLR4 grammar](https://github.com/antlr/grammars-v4/tree/master/cpp), licensed under MIT. ### C++ specification compatibility @@ -21,11 +18,16 @@ While the Java language module is based on an AST, this language module uses a p There are differences, including: - `import` is extracted in Java, while `using` is not extracted due to the fact that it can be placed freely in the code. -More syntactic elements of C/C++ may turn out to be helpful to include in the future, especially those that are newly introduced. +More syntactic elements of C++ may turn out to be helpful to include in the future, especially those that are newly introduced. ### Usage -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). +To use the C++ frontend, add the `-l cpp` flag in the CLI, or use a `JPlagOption` object with `new de.jplag.cpp.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.
diff --git a/languages/cpp/pom.xml b/languages/cpp/pom.xml index 54529df6b..d3cfb4881 100644 --- a/languages/cpp/pom.xml +++ b/languages/cpp/pom.xml @@ -8,25 +8,28 @@ cpp + + + org.antlr + antlr4-runtime + + + de.jplag + language-antlr-utils + ${revision} + + + - com.helger.maven - ph-javacc-maven-plugin + org.antlr + antlr4-maven-plugin - javacc-gen - javacc + antlr4 - generate-sources - - 17 - true - de.jplag.cpp - src/main/javacc - ${project.build.directory}/generated-sources/javacc - diff --git a/languages/cpp2/src/main/antlr4/de/jplag/cpp2/grammar/CPP14Lexer.g4 b/languages/cpp/src/main/antlr4/de/jplag/cpp/grammar/CPP14Lexer.g4 similarity index 100% rename from languages/cpp2/src/main/antlr4/de/jplag/cpp2/grammar/CPP14Lexer.g4 rename to languages/cpp/src/main/antlr4/de/jplag/cpp/grammar/CPP14Lexer.g4 diff --git a/languages/cpp2/src/main/antlr4/de/jplag/cpp2/grammar/CPP14Parser.g4 b/languages/cpp/src/main/antlr4/de/jplag/cpp/grammar/CPP14Parser.g4 similarity index 99% rename from languages/cpp2/src/main/antlr4/de/jplag/cpp2/grammar/CPP14Parser.g4 rename to languages/cpp/src/main/antlr4/de/jplag/cpp/grammar/CPP14Parser.g4 index d3a37438e..1be43aee5 100644 --- a/languages/cpp2/src/main/antlr4/de/jplag/cpp2/grammar/CPP14Parser.g4 +++ b/languages/cpp/src/main/antlr4/de/jplag/cpp/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/cpp/src/main/java/de/jplag/cpp/CPPLanguage.java similarity index 57% rename from languages/cpp2/src/main/java/de/jplag/cpp2/CPPLanguage.java rename to languages/cpp/src/main/java/de/jplag/cpp/CPPLanguage.java index d30647049..c08e53dce 100644 --- a/languages/cpp2/src/main/java/de/jplag/cpp2/CPPLanguage.java +++ b/languages/cpp/src/main/java/de/jplag/cpp/CPPLanguage.java @@ -1,26 +1,19 @@ -package de.jplag.cpp2; - -import java.io.File; -import java.util.List; -import java.util.Set; +package de.jplag.cpp; 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 { - private static final String IDENTIFIER = "cpp2"; - - private final CPPParserAdapter parser; +public class CPPLanguage extends AbstractAntlrLanguage { + private static final String IDENTIFIER = "cpp"; public CPPLanguage() { - parser = new CPPParserAdapter(); + super(new CPPParserAdapter()); } @Override @@ -30,7 +23,7 @@ public String[] suffixes() { @Override public String getName() { - return "C/C++ Parser"; + return "C++ Parser"; } @Override @@ -44,7 +37,12 @@ public int minimumTokenMatch() { } @Override - public List parse(Set files) throws ParsingException { - return this.parser.scan(files); + public boolean tokensHaveSemantics() { + return true; + } + + @Override + public boolean supportsNormalization() { + return true; } } diff --git a/languages/cpp/src/main/java/de/jplag/cpp/CPPListener.java b/languages/cpp/src/main/java/de/jplag/cpp/CPPListener.java new file mode 100644 index 000000000..28a6a88b9 --- /dev/null +++ b/languages/cpp/src/main/java/de/jplag/cpp/CPPListener.java @@ -0,0 +1,275 @@ +package de.jplag.cpp; + +import static de.jplag.cpp.CPPTokenType.APPLY; +import static de.jplag.cpp.CPPTokenType.ASSIGN; +import static de.jplag.cpp.CPPTokenType.BRACED_INIT_BEGIN; +import static de.jplag.cpp.CPPTokenType.BRACED_INIT_END; +import static de.jplag.cpp.CPPTokenType.BREAK; +import static de.jplag.cpp.CPPTokenType.CASE; +import static de.jplag.cpp.CPPTokenType.CATCH_BEGIN; +import static de.jplag.cpp.CPPTokenType.CATCH_END; +import static de.jplag.cpp.CPPTokenType.CLASS_BEGIN; +import static de.jplag.cpp.CPPTokenType.CLASS_END; +import static de.jplag.cpp.CPPTokenType.CONTINUE; +import static de.jplag.cpp.CPPTokenType.DEFAULT; +import static de.jplag.cpp.CPPTokenType.DO_BEGIN; +import static de.jplag.cpp.CPPTokenType.DO_END; +import static de.jplag.cpp.CPPTokenType.ELSE; +import static de.jplag.cpp.CPPTokenType.ENUM_BEGIN; +import static de.jplag.cpp.CPPTokenType.ENUM_END; +import static de.jplag.cpp.CPPTokenType.FOR_BEGIN; +import static de.jplag.cpp.CPPTokenType.FOR_END; +import static de.jplag.cpp.CPPTokenType.FUNCTION_BEGIN; +import static de.jplag.cpp.CPPTokenType.FUNCTION_END; +import static de.jplag.cpp.CPPTokenType.GENERIC; +import static de.jplag.cpp.CPPTokenType.GOTO; +import static de.jplag.cpp.CPPTokenType.IF_BEGIN; +import static de.jplag.cpp.CPPTokenType.IF_END; +import static de.jplag.cpp.CPPTokenType.NEWARRAY; +import static de.jplag.cpp.CPPTokenType.NEWCLASS; +import static de.jplag.cpp.CPPTokenType.QUESTIONMARK; +import static de.jplag.cpp.CPPTokenType.RETURN; +import static de.jplag.cpp.CPPTokenType.STATIC_ASSERT; +import static de.jplag.cpp.CPPTokenType.STRUCT_BEGIN; +import static de.jplag.cpp.CPPTokenType.STRUCT_END; +import static de.jplag.cpp.CPPTokenType.SWITCH_BEGIN; +import static de.jplag.cpp.CPPTokenType.SWITCH_END; +import static de.jplag.cpp.CPPTokenType.THROW; +import static de.jplag.cpp.CPPTokenType.TRY_BEGIN; +import static de.jplag.cpp.CPPTokenType.TRY_END; +import static de.jplag.cpp.CPPTokenType.UNION_BEGIN; +import static de.jplag.cpp.CPPTokenType.UNION_END; +import static de.jplag.cpp.CPPTokenType.VARDEF; +import static de.jplag.cpp.CPPTokenType.WHILE_BEGIN; +import static de.jplag.cpp.CPPTokenType.WHILE_END; + +import java.util.function.Function; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.TerminalNode; + +import de.jplag.TokenType; +import de.jplag.antlr.AbstractAntlrListener; +import de.jplag.antlr.ContextVisitor; +import de.jplag.cpp.grammar.CPP14Parser; +import de.jplag.cpp.grammar.CPP14Parser.AssignmentOperatorContext; +import de.jplag.cpp.grammar.CPP14Parser.BraceOrEqualInitializerContext; +import de.jplag.cpp.grammar.CPP14Parser.BracedInitListContext; +import de.jplag.cpp.grammar.CPP14Parser.ClassKeyContext; +import de.jplag.cpp.grammar.CPP14Parser.ClassSpecifierContext; +import de.jplag.cpp.grammar.CPP14Parser.ConditionalExpressionContext; +import de.jplag.cpp.grammar.CPP14Parser.DeclaratorContext; +import de.jplag.cpp.grammar.CPP14Parser.EnumSpecifierContext; +import de.jplag.cpp.grammar.CPP14Parser.EnumeratorDefinitionContext; +import de.jplag.cpp.grammar.CPP14Parser.FunctionBodyContext; +import de.jplag.cpp.grammar.CPP14Parser.FunctionDefinitionContext; +import de.jplag.cpp.grammar.CPP14Parser.HandlerContext; +import de.jplag.cpp.grammar.CPP14Parser.InitDeclaratorContext; +import de.jplag.cpp.grammar.CPP14Parser.IterationStatementContext; +import de.jplag.cpp.grammar.CPP14Parser.JumpStatementContext; +import de.jplag.cpp.grammar.CPP14Parser.LabeledStatementContext; +import de.jplag.cpp.grammar.CPP14Parser.MemberDeclaratorContext; +import de.jplag.cpp.grammar.CPP14Parser.MemberSpecificationContext; +import de.jplag.cpp.grammar.CPP14Parser.MemberdeclarationContext; +import de.jplag.cpp.grammar.CPP14Parser.NewExpressionContext; +import de.jplag.cpp.grammar.CPP14Parser.NewTypeIdContext; +import de.jplag.cpp.grammar.CPP14Parser.NoPointerDeclaratorContext; +import de.jplag.cpp.grammar.CPP14Parser.ParameterDeclarationContext; +import de.jplag.cpp.grammar.CPP14Parser.PostfixExpressionContext; +import de.jplag.cpp.grammar.CPP14Parser.SelectionStatementContext; +import de.jplag.cpp.grammar.CPP14Parser.SimpleDeclarationContext; +import de.jplag.cpp.grammar.CPP14Parser.SimpleTypeSpecifierContext; +import de.jplag.cpp.grammar.CPP14Parser.StaticAssertDeclarationContext; +import de.jplag.cpp.grammar.CPP14Parser.TemplateArgumentContext; +import de.jplag.cpp.grammar.CPP14Parser.TemplateDeclarationContext; +import de.jplag.cpp.grammar.CPP14Parser.ThrowExpressionContext; +import de.jplag.cpp.grammar.CPP14Parser.TryBlockContext; +import de.jplag.cpp.grammar.CPP14Parser.UnaryExpressionContext; +import de.jplag.cpp.grammar.CPP14Parser.UnqualifiedIdContext; +import de.jplag.semantics.CodeSemantics; +import de.jplag.semantics.VariableAccessType; +import de.jplag.semantics.VariableRegistry; +import de.jplag.semantics.VariableScope; + +/** + * 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).withSemantics(CodeSemantics::new); + mapClass(ClassKeyContext::Class, CLASS_BEGIN, CLASS_END); + mapClass(ClassKeyContext::Struct, STRUCT_BEGIN, STRUCT_END); // structs are basically just classes + visit(EnumSpecifierContext.class).map(ENUM_BEGIN, ENUM_END).withSemantics(CodeSemantics::createControl); + + visit(FunctionDefinitionContext.class).map(FUNCTION_BEGIN, FUNCTION_END).addLocalScope().withSemantics(CodeSemantics::createControl); + + statementRules(); + + visit(TryBlockContext.class).map(TRY_BEGIN, TRY_END).addLocalScope().withSemantics(CodeSemantics::createControl); + visit(HandlerContext.class).map(CATCH_BEGIN, CATCH_END).addLocalScope().withSemantics(CodeSemantics::createControl); + + visit(ThrowExpressionContext.class).map(THROW).withSemantics(CodeSemantics::createControl); + + visit(NewExpressionContext.class, rule -> rule.newInitializer() != null).map(NEWCLASS).withSemantics(CodeSemantics::new); + visit(NewExpressionContext.class, rule -> rule.newInitializer() == null).map(NEWARRAY).withSemantics(CodeSemantics::new); + + visit(TemplateDeclarationContext.class).map(GENERIC).withSemantics(CodeSemantics::new); + + visit(AssignmentOperatorContext.class).map(ASSIGN).withSemantics(CodeSemantics::new) + .onEnter((rule, varReg) -> varReg.setNextVariableAccessType(VariableAccessType.WRITE)); + visit(UnaryExpressionContext.class, rule -> rule.PlusPlus() != null || rule.MinusMinus() != null).map(ASSIGN) + .withSemantics(CodeSemantics::new).onEnter((rule, varReg) -> varReg.setNextVariableAccessType(VariableAccessType.READ_WRITE)); + + visit(StaticAssertDeclarationContext.class).map(STATIC_ASSERT).withSemantics(CodeSemantics::createControl); + visit(EnumeratorDefinitionContext.class).map(VARDEF).withSemantics(CodeSemantics::new) + .onEnter((rule, varReg) -> varReg.setNextVariableAccessType(VariableAccessType.WRITE)); + visit(BracedInitListContext.class).map(BRACED_INIT_BEGIN, BRACED_INIT_END).withSemantics(CodeSemantics::new); + + typeSpecifierRule(); + declarationRules(); + expressionRules(); + idRules(); + } + + private void statementRules() { + visit(IterationStatementContext.class, rule -> rule.Do() != null).map(DO_BEGIN, DO_END).addLocalScope().withLoopSemantics(); + visit(IterationStatementContext.class, rule -> rule.For() != null).map(FOR_BEGIN, FOR_END).addLocalScope().withLoopSemantics(); + visit(IterationStatementContext.class, rule -> rule.While() != null && rule.Do() == null).map(WHILE_BEGIN, WHILE_END).addLocalScope() + .withLoopSemantics(); + + visit(SelectionStatementContext.class, rule -> rule.Switch() != null).map(SWITCH_BEGIN, SWITCH_END).addLocalScope() + .withSemantics(CodeSemantics::createControl); + visit(SelectionStatementContext.class, rule -> rule.If() != null).map(IF_BEGIN, IF_END).addLocalScope() + .withSemantics(CodeSemantics::createControl); + // possible problem: variable from if visible in else, but in reality is not -- doesn't really matter + visit(CPP14Parser.Else).map(ELSE).withSemantics(CodeSemantics::createControl); + + visit(LabeledStatementContext.class, rule -> rule.Case() != null).map(CASE).withSemantics(CodeSemantics::createControl); + visit(LabeledStatementContext.class, rule -> rule.Default() != null).map(DEFAULT).withSemantics(CodeSemantics::createControl); + + visit(JumpStatementContext.class, rule -> rule.Break() != null).map(BREAK).withSemantics(CodeSemantics::createControl); + visit(JumpStatementContext.class, rule -> rule.Continue() != null).map(CONTINUE).withSemantics(CodeSemantics::createControl); + visit(JumpStatementContext.class, rule -> rule.Goto() != null).map(GOTO).withSemantics(CodeSemantics::createControl); + visit(JumpStatementContext.class, rule -> rule.Return() != null).map(RETURN).withSemantics(CodeSemantics::createControl); + } + + private void typeSpecifierRule() { + visit(SimpleTypeSpecifierContext.class, rule -> { + if (hasAncestor(rule, MemberdeclarationContext.class, FunctionDefinitionContext.class)) { + return true; + } + SimpleDeclarationContext parent = getAncestor(rule, SimpleDeclarationContext.class, TemplateArgumentContext.class, + FunctionDefinitionContext.class); + if (parent == null) { + return false; + } + NoPointerDeclaratorContext noPointerDecl = getDescendant(parent, NoPointerDeclaratorContext.class); + return !noPointerInFunctionCallContext(noPointerDecl) && !hasAncestor(rule, NewTypeIdContext.class); + }).map(VARDEF).withSemantics(CodeSemantics::new).onEnter((context, variableRegistry) -> { + SimpleDeclarationContext parent = getAncestor(context, SimpleDeclarationContext.class); + if (parent == null) { // at this point we know parent exists + throw new IllegalStateException(); + } + // boolean typeMutable = context.theTypeName() != null; // block is duplicate to member variable register + // possible issue: what if multiple variables are declared in the same line? + variableRegistry.setNextVariableAccessType(VariableAccessType.WRITE); + if (parent.initDeclaratorList() == null) { + return; + } + for (InitDeclaratorContext dec : parent.initDeclaratorList().initDeclarator()) { + String name = dec.declarator().pointerDeclarator().noPointerDeclarator().getText(); + VariableScope scope = variableRegistry.inLocalScope() ? VariableScope.LOCAL : VariableScope.FILE; + variableRegistry.registerVariable(name, scope, true); + } + }); + } + + private void declarationRules() { + mapApply(visit(SimpleDeclarationContext.class, rule -> { + if (!hasAncestor(rule, FunctionBodyContext.class)) { + return false; + } + + NoPointerDeclaratorContext noPointerDecl = getDescendant(rule, NoPointerDeclaratorContext.class); + return noPointerInFunctionCallContext(noPointerDecl); + })); + + mapApply(visit(InitDeclaratorContext.class, rule -> rule.initializer() != null && rule.initializer().LeftParen() != null)); + visit(DeclaratorContext.class, rule -> { + ParserRuleContext parent = rule.getParent(); + BraceOrEqualInitializerContext desc = getDescendant(parent, BraceOrEqualInitializerContext.class); + return (desc != null && desc.Assign() != null && (parent == desc.getParent() || parent == desc.getParent().getParent())); + }).map(ASSIGN).withSemantics(CodeSemantics::new).onEnter((ctx, varReg) -> varReg.setNextVariableAccessType(VariableAccessType.WRITE)); + + visit(ParameterDeclarationContext.class).map(VARDEF).withSemantics(CodeSemantics::new).onEnter((ctx, varReg) -> { + // don't register parameters in function declarations, e.g. bc6h_enc lines 117-120 + if (hasAncestor(ctx, FunctionDefinitionContext.class, SimpleDeclarationContext.class)) { + CPP14Parser.PointerDeclaratorContext pd = ctx.declarator().pointerDeclarator(); + String name = pd.noPointerDeclarator().getText(); + varReg.registerVariable(name, VariableScope.LOCAL, true); + varReg.setNextVariableAccessType(VariableAccessType.WRITE); + } + }); + } + + private void expressionRules() { + visit(ConditionalExpressionContext.class, rule -> rule.Question() != null).map(QUESTIONMARK).withSemantics(CodeSemantics::new); + + mapApply(visit(PostfixExpressionContext.class, rule -> rule.LeftParen() != null)); + visit(PostfixExpressionContext.class, rule -> rule.PlusPlus() != null || rule.MinusMinus() != null).map(ASSIGN) + .withSemantics(CodeSemantics::new).onEnter((rule, varReg) -> varReg.setNextVariableAccessType(VariableAccessType.READ_WRITE)); + } + + private void idRules() { + visit(UnqualifiedIdContext.class).onEnter((ctx, varReg) -> { + ParserRuleContext parentCtx = ctx.getParent().getParent(); + if (!parentCtx.getParent().getParent().getText().contains("(")) { + boolean isClassVariable = parentCtx.getClass() == PostfixExpressionContext.class // after dot + && ((PostfixExpressionContext) parentCtx).postfixExpression().getText().equals("this"); + varReg.registerVariableAccess(ctx.getText(), isClassVariable); + } + }); + } + + private void mapApply(ContextVisitor visitor) { + visitor.onExit((ctx, varReg) -> varReg.setMutableWrite(false)).onEnter((ctx, varReg) -> { + varReg.addAllNonLocalVariablesAsReads(); + varReg.setMutableWrite(true); + }).map(APPLY).withControlSemantics(); + } + + /** + * @return true of this context represents a function call + */ + private static boolean noPointerInFunctionCallContext(NoPointerDeclaratorContext context) { + return context != null && (context.parametersAndQualifiers() != null || context.LeftParen() != null); + } + + private void mapClass(Function getTerminal, TokenType beginTokenType, TokenType endTokenType) { + visit(ClassSpecifierContext.class, rule -> { + ClassKeyContext classKey = rule.classHead().classKey(); + return classKey != null && getTerminal.apply(classKey) != null; + }).map(beginTokenType, endTokenType).addClassScope().withSemantics(CodeSemantics::createControl).onEnter(this::registerClassVariables); + } + + private void registerClassVariables(ClassSpecifierContext context, VariableRegistry variableRegistry) { + MemberSpecificationContext members = context.memberSpecification(); + if (members != null) { // is null if class has no members + for (MemberdeclarationContext member : members.memberdeclaration()) { + if (member.memberDeclaratorList() != null) { + for (MemberDeclaratorContext memberDec : member.memberDeclaratorList().memberDeclarator()) { + DeclaratorContext dec = memberDec.declarator(); + if (dec != null) { // is null in some weird case, see bc6h_enc line 1100 + String name = dec.pointerDeclarator().noPointerDeclarator().getText(); + variableRegistry.registerVariable(name, VariableScope.CLASS, true); + } + } + } + } + } + } +} diff --git a/languages/cpp/src/main/java/de/jplag/cpp/CPPParserAdapter.java b/languages/cpp/src/main/java/de/jplag/cpp/CPPParserAdapter.java new file mode 100644 index 000000000..d1bc12a6b --- /dev/null +++ b/languages/cpp/src/main/java/de/jplag/cpp/CPPParserAdapter.java @@ -0,0 +1,43 @@ +package de.jplag.cpp; + +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.AbstractParser; +import de.jplag.antlr.AbstractAntlrListener; +import de.jplag.antlr.AbstractAntlrParserAdapter; +import de.jplag.cpp.grammar.CPP14Lexer; +import de.jplag.cpp.grammar.CPP14Parser; + +/** + * The adapter between {@link AbstractParser} and the ANTLR based parser of this language module. + */ +public class CPPParserAdapter extends AbstractAntlrParserAdapter { + private static final CPPListener listener = new CPPListener(); + + public CPPParserAdapter() { + super(true); + } + + @Override + protected Lexer createLexer(CharStream input) { + return new CPP14Lexer(input); + } + + @Override + protected CPP14Parser createParser(CommonTokenStream tokenStream) { + return new CPP14Parser(tokenStream); + } + + @Override + protected ParserRuleContext getEntryContext(CPP14Parser parser) { + return parser.translationUnit(); + } + + @Override + protected AbstractAntlrListener getListener() { + return listener; + } +} 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..0bf830cd6 100644 --- a/languages/cpp/src/main/java/de/jplag/cpp/CPPTokenType.java +++ b/languages/cpp/src/main/java/de/jplag/cpp/CPPTokenType.java @@ -2,70 +2,56 @@ import de.jplag.TokenType; +/** + * C++ token types extracted by this language module. + */ public enum CPPTokenType implements TokenType { - C_BLOCK_BEGIN("BLOCK{"), - C_BLOCK_END("}BLOCK"), - C_QUESTIONMARK("COND"), - C_ELLIPSIS("..."), - C_ASSIGN("ASSIGN"), - C_DOT("DOT"), - C_ARROW("ARROW"), - C_ARROWSTAR("ARROWSTAR"), - C_AUTO("AUTO"), - C_BREAK("BREAK"), - C_CASE("CASE"), - C_CATCH("CATCH"), - C_CHAR("CHAR"), - C_CONST("CONST"), - C_CONTINUE("CONTINUE"), - C_DEFAULT("DEFAULT"), - C_DELETE("DELETE"), - C_DO("DO"), - C_DOUBLE("DOUBLE"), - C_ELSE("ELSE"), - C_ENUM("ENUM"), - C_EXTERN("EXTERN"), - C_FLOAT("FLOAT"), - C_FOR("FOR"), - C_FRIEND("FRIEND"), - C_GOTO("GOTO"), - C_IF("IF"), - C_INLINE("INLINE"), - C_INT("INT"), - C_LONG("LONG"), - C_NEW("NEW"), - C_PRIVATE("PRIVATE"), - C_PROTECTED("PROTECTED"), - C_PUBLIC("PUBLIC"), - C_REDECLARED("REDECLARED"), - C_REGISTER("REGISTER"), - C_RETURN("RETURN"), - C_SHORT("SHORT"), - C_SIGNED("SIGNED"), - C_SIZEOF("SIZEOF"), - C_STATIC("STATIC"), - C_STRUCT("STRUCT"), - C_CLASS("CLASS"), - C_SWITCH("SWITCH"), - C_TEMPLATE("TEMPLATE"), - C_THIS("THIS"), - C_TRY("TRY"), - C_TYPEDEF("TYPEDEF"), - C_UNION("UNION"), - C_UNSIGNED("UNSIGNED"), - C_VIRTUAL("VIRTUAL"), - C_VOID("VOID"), - C_VOLATILE("VOLATILE"), - C_WHILE("WHILE"), - C_OPERATOR("OPERATOR"), - C_THROW("THROW"), - C_ID("ID"), - C_FUN("FUN"), - C_DOTSTAR("DOTSTAR"), - C_NULL("NULL"); + CLASS_BEGIN("CLASS{"), + CLASS_END("}CLASS"), + STRUCT_BEGIN("STRUCT{"), + STRUCT_END("}STRUCT"), + ENUM_BEGIN("ENUM{"), + ENUM_END("}ENUM"), + UNION_BEGIN("UNION{"), + UNION_END("}UNION"), + FUNCTION_BEGIN("FUNCTION{"), + FUNCTION_END("}FUNCTION"), + DO_BEGIN("DO{"), + DO_END("}DO"), + WHILE_BEGIN("WHILE{"), + WHILE_END("}WHILE"), + FOR_BEGIN("FOR{"), + FOR_END("}FOR"), + SWITCH_BEGIN("SWITCH{"), + SWITCH_END("}SWITCH"), + CASE("CASE"), + TRY_BEGIN("TRY{"), + TRY_END("}TRY"), + CATCH_BEGIN("CATCH{"), + CATCH_END("}CATCH"), + IF_BEGIN("IF{"), + IF_END("}IF"), + ELSE("ELSE"), + BREAK("BREAK"), + CONTINUE("CONTINUE"), + GOTO("GOTO"), + RETURN("RETURN"), + THROW("THROW"), + NEWCLASS("NEWCLASS"), + GENERIC("GENERIC"), + NEWARRAY("NEWARRAY"), + BRACED_INIT_BEGIN("BRACED_INIT{"), + BRACED_INIT_END("}BRACED_INIT"), + ASSIGN("ASSIGN"), + STATIC_ASSERT("STATIC_ASSERT"), + VARDEF("VARDEF"), + QUESTIONMARK("COND"), + DEFAULT("DEFAULT"), + APPLY("APPLY"); private final String description; + @Override public String getDescription() { return this.description; } diff --git a/languages/cpp/src/test/java/de/jplag/cpp/CppLanguageTest.java b/languages/cpp/src/test/java/de/jplag/cpp/CppLanguageTest.java new file mode 100644 index 000000000..c885c4562 --- /dev/null +++ b/languages/cpp/src/test/java/de/jplag/cpp/CppLanguageTest.java @@ -0,0 +1,105 @@ +package de.jplag.cpp; + +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/cpp/src/test/resources/de/jplag/cpp/CallOutsideMethodInClass.cpp b/languages/cpp/src/test/resources/de/jplag/cpp/CallOutsideMethodInClass.cpp new file mode 100644 index 000000000..847f41942 --- /dev/null +++ b/languages/cpp/src/test/resources/de/jplag/cpp/CallOutsideMethodInClass.cpp @@ -0,0 +1,3 @@ +class A { + int x = square(3); +}; \ No newline at end of file diff --git a/languages/cpp/src/test/resources/de/jplag/cpp/FunctionCall.cpp b/languages/cpp/src/test/resources/de/jplag/cpp/FunctionCall.cpp new file mode 100644 index 000000000..8808bd9c0 --- /dev/null +++ b/languages/cpp/src/test/resources/de/jplag/cpp/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/cpp/src/test/resources/de/jplag/cpp/IfElse.cpp b/languages/cpp/src/test/resources/de/jplag/cpp/IfElse.cpp new file mode 100644 index 000000000..8410214c2 --- /dev/null +++ b/languages/cpp/src/test/resources/de/jplag/cpp/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/cpp/src/test/resources/de/jplag/cpp/IntArray.cpp b/languages/cpp/src/test/resources/de/jplag/cpp/IntArray.cpp new file mode 100644 index 000000000..e78822834 --- /dev/null +++ b/languages/cpp/src/test/resources/de/jplag/cpp/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/cpp/src/test/resources/de/jplag/cpp/Loop.cpp b/languages/cpp/src/test/resources/de/jplag/cpp/Loop.cpp new file mode 100644 index 000000000..ff20d1a49 --- /dev/null +++ b/languages/cpp/src/test/resources/de/jplag/cpp/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/cpp/src/test/resources/de/jplag/cpp/Union.cpp b/languages/cpp/src/test/resources/de/jplag/cpp/Union.cpp new file mode 100644 index 000000000..0134add2d --- /dev/null +++ b/languages/cpp/src/test/resources/de/jplag/cpp/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/cpp/src/test/resources/de/jplag/cpp/bc6h_enc.h b/languages/cpp/src/test/resources/de/jplag/cpp/bc6h_enc.h new file mode 100644 index 000000000..35e250237 --- /dev/null +++ b/languages/cpp/src/test/resources/de/jplag/cpp/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/cpp2/src/main/java/de/jplag/cpp2/CPPParserAdapter.java b/languages/cpp2/src/main/java/de/jplag/cpp2/CPPParserAdapter.java deleted file mode 100644 index c123dc29e..000000000 --- a/languages/cpp2/src/main/java/de/jplag/cpp2/CPPParserAdapter.java +++ /dev/null @@ -1,66 +0,0 @@ -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.CommonTokenStream; -import org.antlr.v4.runtime.tree.ParseTreeWalker; - -import de.jplag.AbstractParser; -import de.jplag.ParsingException; -import de.jplag.Token; -import de.jplag.TokenType; -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; - - /** - * {@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(); - - ParseTreeWalker.DEFAULT.walk(new CPPTokenListener(this), translationUnit); - } catch (IOException e) { - throw new ParsingException(file, e); - } - tokens.add(Token.fileEnd(currentFile)); - } - return tokens; - } - - /** - * 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)); - } - -} 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 deleted file mode 100644 index 018717717..000000000 --- a/languages/cpp2/src/main/java/de/jplag/cpp2/CPPTokenType.java +++ /dev/null @@ -1,62 +0,0 @@ -package de.jplag.cpp2; - -import de.jplag.TokenType; - -/** - * C++ token types extracted by this language module. - */ -public enum CPPTokenType implements TokenType { - CLASS_BEGIN("CLASS{"), - CLASS_END("}CLASS"), - STRUCT_BEGIN("STRUCT{"), - STRUCT_END("}STRUCT"), - ENUM_BEGIN("ENUM{"), - ENUM_END("}ENUM"), - UNION_BEGIN("UNION{"), - UNION_END("}UNION"), - FUNCTION_BEGIN("FUNCTION{"), - FUNCTION_END("}FUNCTION"), - DO_BEGIN("DO{"), - DO_END("}DO"), - WHILE_BEGIN("WHILE{"), - WHILE_END("}WHILE"), - FOR_BEGIN("FOR{"), - FOR_END("}FOR"), - SWITCH_BEGIN("SWITCH{"), - SWITCH_END("}SWITCH"), - CASE("CASE"), - TRY("TRY"), - CATCH_BEGIN("CATCH{"), - CATCH_END("}CATCH"), - IF_BEGIN("IF{"), - IF_END("}IF"), - ELSE("ELSE"), - BREAK("BREAK"), - CONTINUE("CONTINUE"), - GOTO("GOTO"), - RETURN("RETURN"), - THROW("THROW"), - NEWCLASS("NEWCLASS"), - GENERIC("GENERIC"), - NEWARRAY("NEWARRAY"), - BRACED_INIT_BEGIN("BRACED_INIT{"), - BRACED_INIT_END("}BRACED_INIT"), - ASSIGN("ASSIGN"), - STATIC_ASSERT("STATIC_ASSERT"), - VARDEF("VARDEF"), - QUESTIONMARK("COND"), - ATTRIBUTE("ATTRIBUTE"), - DEFAULT("DEFAULT"), - APPLY("APPLY"); - - private final String description; - - @Override - public String getDescription() { - return this.description; - } - - CPPTokenType(String description) { - this.description = description; - } -} 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/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/pom.xml b/languages/csharp/pom.xml index 9bf5f4b66..12213357f 100644 --- a/languages/csharp/pom.xml +++ b/languages/csharp/pom.xml @@ -13,6 +13,11 @@ org.antlr antlr4-runtime + + de.jplag + language-antlr-utils + ${revision} + 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 63% 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..aeeb53728 100644 --- a/languages/csharp/src/main/java/de/jplag/csharp/Language.java +++ b/languages/csharp/src/main/java/de/jplag/csharp/CSharpLanguage.java @@ -1,29 +1,21 @@ package de.jplag.csharp; -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; /** * C# language with full support of C# 6 features and below. - * @author Timur Saglam */ @MetaInfServices(de.jplag.Language.class) -public class Language implements de.jplag.Language { +public class CSharpLanguage extends AbstractAntlrLanguage { private static final String NAME = "C# 6 Parser"; private static final String IDENTIFIER = "csharp"; private static final String[] FILE_ENDINGS = new String[] {".cs", ".CS"}; private static final int DEFAULT_MIN_TOKEN_MATCH = 8; - private final CSharpParserAdapter parser; - - public Language() { - parser = new CSharpParserAdapter(); + public CSharpLanguage() { + super(new CSharpParserAdapter()); } @Override @@ -45,9 +37,4 @@ public String getIdentifier() { public int minimumTokenMatch() { return DEFAULT_MIN_TOKEN_MATCH; } - - @Override - public List parse(Set files) throws ParsingException { - return parser.parse(files); - } } diff --git a/languages/csharp/src/main/java/de/jplag/csharp/CSharpListener.java b/languages/csharp/src/main/java/de/jplag/csharp/CSharpListener.java index 65d04d5b7..6cc568505 100644 --- a/languages/csharp/src/main/java/de/jplag/csharp/CSharpListener.java +++ b/languages/csharp/src/main/java/de/jplag/csharp/CSharpListener.java @@ -19,7 +19,6 @@ import static de.jplag.csharp.CSharpTokenType.CONTINUE; import static de.jplag.csharp.CSharpTokenType.DELEGATE; import static de.jplag.csharp.CSharpTokenType.DESTRUCTOR; -import static de.jplag.csharp.CSharpTokenType.DO; import static de.jplag.csharp.CSharpTokenType.ENUM; import static de.jplag.csharp.CSharpTokenType.ENUMERAL; import static de.jplag.csharp.CSharpTokenType.ENUM_BEGIN; @@ -28,8 +27,6 @@ import static de.jplag.csharp.CSharpTokenType.FIELD; import static de.jplag.csharp.CSharpTokenType.FINALLY; import static de.jplag.csharp.CSharpTokenType.FIXED; -import static de.jplag.csharp.CSharpTokenType.FOR; -import static de.jplag.csharp.CSharpTokenType.FOREACH; import static de.jplag.csharp.CSharpTokenType.GOTO; import static de.jplag.csharp.CSharpTokenType.IF; import static de.jplag.csharp.CSharpTokenType.IF_BEGIN; @@ -41,9 +38,12 @@ import static de.jplag.csharp.CSharpTokenType.INVOCATION; import static de.jplag.csharp.CSharpTokenType.LOCAL_VARIABLE; import static de.jplag.csharp.CSharpTokenType.LOCK; +import static de.jplag.csharp.CSharpTokenType.LOOP_BEGIN; +import static de.jplag.csharp.CSharpTokenType.LOOP_END; import static de.jplag.csharp.CSharpTokenType.METHOD; import static de.jplag.csharp.CSharpTokenType.METHOD_BEGIN; import static de.jplag.csharp.CSharpTokenType.METHOD_END; +import static de.jplag.csharp.CSharpTokenType.NAMESPACE; import static de.jplag.csharp.CSharpTokenType.NAMESPACE_BEGIN; import static de.jplag.csharp.CSharpTokenType.NAMESPACE_END; import static de.jplag.csharp.CSharpTokenType.OBJECT_CREATION; @@ -59,25 +59,39 @@ import static de.jplag.csharp.CSharpTokenType.TRY; import static de.jplag.csharp.CSharpTokenType.UNCHECKED; import static de.jplag.csharp.CSharpTokenType.UNSAFE; -import static de.jplag.csharp.CSharpTokenType.USING; import static de.jplag.csharp.CSharpTokenType.USING_DIRECTIVE; -import static de.jplag.csharp.CSharpTokenType.WHILE; - -import org.antlr.v4.runtime.Token; - +import static de.jplag.csharp.grammar.CSharpParser.ELSE; +import static de.jplag.csharp.grammar.CSharpParser.OP_ADD_ASSIGNMENT; +import static de.jplag.csharp.grammar.CSharpParser.OP_AND_ASSIGNMENT; +import static de.jplag.csharp.grammar.CSharpParser.OP_COALESCING_ASSIGNMENT; +import static de.jplag.csharp.grammar.CSharpParser.OP_DEC; +import static de.jplag.csharp.grammar.CSharpParser.OP_DIV_ASSIGNMENT; +import static de.jplag.csharp.grammar.CSharpParser.OP_INC; +import static de.jplag.csharp.grammar.CSharpParser.OP_MOD_ASSIGNMENT; +import static de.jplag.csharp.grammar.CSharpParser.OP_MULT_ASSIGNMENT; +import static de.jplag.csharp.grammar.CSharpParser.OP_OR_ASSIGNMENT; +import static de.jplag.csharp.grammar.CSharpParser.OP_SUB_ASSIGNMENT; +import static de.jplag.csharp.grammar.CSharpParser.OP_XOR_ASSIGNMENT; + +import org.antlr.v4.runtime.ParserRuleContext; + +import de.jplag.antlr.AbstractAntlrListener; import de.jplag.csharp.grammar.CSharpParser.Accessor_bodyContext; import de.jplag.csharp.grammar.CSharpParser.Accessor_declarationsContext; import de.jplag.csharp.grammar.CSharpParser.Array_initializerContext; import de.jplag.csharp.grammar.CSharpParser.Assignment_operatorContext; import de.jplag.csharp.grammar.CSharpParser.AttributeContext; +import de.jplag.csharp.grammar.CSharpParser.BodyContext; import de.jplag.csharp.grammar.CSharpParser.BreakStatementContext; -import de.jplag.csharp.grammar.CSharpParser.Catch_clausesContext; +import de.jplag.csharp.grammar.CSharpParser.CheckedExpressionContext; import de.jplag.csharp.grammar.CSharpParser.CheckedStatementContext; import de.jplag.csharp.grammar.CSharpParser.Class_bodyContext; import de.jplag.csharp.grammar.CSharpParser.Class_definitionContext; +import de.jplag.csharp.grammar.CSharpParser.Common_member_declarationContext; import de.jplag.csharp.grammar.CSharpParser.Constant_declarationContext; import de.jplag.csharp.grammar.CSharpParser.Constructor_declarationContext; import de.jplag.csharp.grammar.CSharpParser.ContinueStatementContext; +import de.jplag.csharp.grammar.CSharpParser.Conversion_operator_declaratorContext; import de.jplag.csharp.grammar.CSharpParser.Delegate_definitionContext; import de.jplag.csharp.grammar.CSharpParser.Destructor_definitionContext; import de.jplag.csharp.grammar.CSharpParser.DoStatementContext; @@ -94,425 +108,160 @@ import de.jplag.csharp.grammar.CSharpParser.IfStatementContext; import de.jplag.csharp.grammar.CSharpParser.If_bodyContext; import de.jplag.csharp.grammar.CSharpParser.Indexer_declarationContext; -import de.jplag.csharp.grammar.CSharpParser.Interface_bodyContext; import de.jplag.csharp.grammar.CSharpParser.Interface_definitionContext; +import de.jplag.csharp.grammar.CSharpParser.Local_constant_declarationContext; import de.jplag.csharp.grammar.CSharpParser.Local_variable_declarationContext; import de.jplag.csharp.grammar.CSharpParser.LockStatementContext; import de.jplag.csharp.grammar.CSharpParser.Method_bodyContext; import de.jplag.csharp.grammar.CSharpParser.Method_declarationContext; import de.jplag.csharp.grammar.CSharpParser.Method_invocationContext; import de.jplag.csharp.grammar.CSharpParser.Namespace_bodyContext; +import de.jplag.csharp.grammar.CSharpParser.Namespace_declarationContext; +import de.jplag.csharp.grammar.CSharpParser.Namespace_or_type_nameContext; import de.jplag.csharp.grammar.CSharpParser.Object_creation_expressionContext; import de.jplag.csharp.grammar.CSharpParser.Operator_declarationContext; import de.jplag.csharp.grammar.CSharpParser.Property_declarationContext; import de.jplag.csharp.grammar.CSharpParser.ReturnStatementContext; +import de.jplag.csharp.grammar.CSharpParser.Shift_expressionContext; +import de.jplag.csharp.grammar.CSharpParser.Specific_catch_clauseContext; import de.jplag.csharp.grammar.CSharpParser.Struct_bodyContext; import de.jplag.csharp.grammar.CSharpParser.Struct_definitionContext; import de.jplag.csharp.grammar.CSharpParser.SwitchStatementContext; import de.jplag.csharp.grammar.CSharpParser.Switch_sectionContext; import de.jplag.csharp.grammar.CSharpParser.ThrowStatementContext; import de.jplag.csharp.grammar.CSharpParser.TryStatementContext; +import de.jplag.csharp.grammar.CSharpParser.Type_argument_listContext; import de.jplag.csharp.grammar.CSharpParser.UncheckedExpressionContext; +import de.jplag.csharp.grammar.CSharpParser.UncheckedStatementContext; import de.jplag.csharp.grammar.CSharpParser.UnsafeStatementContext; -import de.jplag.csharp.grammar.CSharpParser.UsingStatementContext; -import de.jplag.csharp.grammar.CSharpParser.Using_directivesContext; +import de.jplag.csharp.grammar.CSharpParser.UsingAliasDirectiveContext; +import de.jplag.csharp.grammar.CSharpParser.UsingNamespaceDirectiveContext; +import de.jplag.csharp.grammar.CSharpParser.UsingStaticDirectiveContext; import de.jplag.csharp.grammar.CSharpParser.WhileStatementContext; -import de.jplag.csharp.grammar.CSharpParserBaseListener; /** - * Listener class for visiting the C# ANTLR parse tree. Transforms selected ANTLR token into JPlag tokens. - * @author Timur Saglam + * Extracts tokens for the {@link CSharpLanguage} */ -public class CSharpListener extends CSharpParserBaseListener { - - private final CSharpParserAdapter parserAdapter; - - /** - * Creates the listener. - * @param parserAdapter is the JPlag parser adapter which receives the transformed tokens. - */ - public CSharpListener(CSharpParserAdapter parserAdapter) { - this.parserAdapter = parserAdapter; - } - - /** - * Transforms an ANTLR Token into a JPlag token and transfers it to the token adapter. - * @param targetType is the type of the JPlag token to be created. - * @param token is the ANTLR token. - */ - private void transformToken(CSharpTokenType targetType, Token token) { - parserAdapter.addToken(targetType, token.getLine(), token.getCharPositionInLine() + 1, token.getText().length()); - } - - @Override - public void enterMethod_invocation(Method_invocationContext context) { - transformToken(INVOCATION, context.getStart()); - super.enterMethod_invocation(context); - } - - @Override - public void enterObject_creation_expression(Object_creation_expressionContext context) { - transformToken(OBJECT_CREATION, context.getStart()); - super.enterObject_creation_expression(context); - } - - @Override - public void enterArray_initializer(Array_initializerContext context) { - transformToken(ARRAY_CREATION, context.getStart()); - super.enterArray_initializer(context); - } - - @Override - public void enterAssignment_operator(Assignment_operatorContext context) { - transformToken(ASSIGNMENT, context.getStart()); - super.enterAssignment_operator(context); - } - - @Override - public void enterIfStatement(IfStatementContext context) { - transformToken(IF, context.getStart()); - super.enterIfStatement(context); - } - - @Override - public void enterIf_body(If_bodyContext context) { - transformToken(IF_BEGIN, context.getStart()); - super.enterIf_body(context); - } - - @Override - public void exitIf_body(If_bodyContext context) { - transformToken(IF_END, context.getStop()); - super.exitIf_body(context); - } - - @Override - public void enterSwitch_section(Switch_sectionContext context) { - transformToken(SWITCH_BEGIN, context.getStart()); - super.enterSwitch_section(context); - } - - @Override - public void exitSwitch_section(Switch_sectionContext context) { - transformToken(SWITCH_END, context.getStop()); - super.exitSwitch_section(context); - } - - @Override - public void enterSwitchStatement(SwitchStatementContext context) { - transformToken(CASE, context.getStart()); - super.enterSwitchStatement(context); - } - - @Override - public void enterDoStatement(DoStatementContext context) { - transformToken(DO, context.getStart()); - super.enterDoStatement(context); - } - - @Override - public void enterWhileStatement(WhileStatementContext context) { - transformToken(WHILE, context.getStart()); - super.enterWhileStatement(context); - } - - @Override - public void enterForStatement(ForStatementContext context) { - transformToken(FOR, context.getStart()); - super.enterForStatement(context); - } - - @Override - public void enterForeachStatement(ForeachStatementContext context) { - transformToken(FOREACH, context.getStart()); - super.enterForeachStatement(context); - } - - @Override - public void enterBreakStatement(BreakStatementContext context) { - transformToken(BREAK, context.getStart()); - super.enterBreakStatement(context); - } - - @Override - public void enterContinueStatement(ContinueStatementContext context) { - transformToken(CONTINUE, context.getStart()); - super.enterContinueStatement(context); - } - - @Override - public void enterGotoStatement(GotoStatementContext context) { - transformToken(GOTO, context.getStart()); - super.enterGotoStatement(context); - } - - @Override - public void enterReturnStatement(ReturnStatementContext context) { - transformToken(RETURN, context.getStart()); - super.enterReturnStatement(context); - } - - @Override - public void enterThrowStatement(ThrowStatementContext context) { - transformToken(THROW, context.getStart()); - super.enterThrowStatement(context); - } - - @Override - public void enterCheckedStatement(CheckedStatementContext context) { - transformToken(CHECKED, context.getStart()); - super.enterCheckedStatement(context); - } - - @Override - public void enterUncheckedExpression(UncheckedExpressionContext context) { - transformToken(UNCHECKED, context.getStart()); - super.enterUncheckedExpression(context); - } - - @Override - public void enterLockStatement(LockStatementContext context) { - transformToken(LOCK, context.getStart()); - super.enterLockStatement(context); - } - - @Override - public void enterUsingStatement(UsingStatementContext context) { - transformToken(USING, context.getStart()); - super.enterUsingStatement(context); - } - - @Override - public void enterTryStatement(TryStatementContext context) { - transformToken(TRY, context.getStart()); - super.enterTryStatement(context); - } - - @Override - public void enterCatch_clauses(Catch_clausesContext context) { - transformToken(CATCH, context.getStart()); - super.enterCatch_clauses(context); - } - - @Override - public void enterFinally_clause(Finally_clauseContext context) { - transformToken(FINALLY, context.getStart()); - super.enterFinally_clause(context); - } - - @Override - public void enterNamespace_body(Namespace_bodyContext context) { - transformToken(NAMESPACE_BEGIN, context.getStart()); - super.enterNamespace_body(context); - } - - @Override - public void exitNamespace_body(Namespace_bodyContext context) { - transformToken(NAMESPACE_END, context.getStop()); - super.exitNamespace_body(context); - } - - @Override - public void enterUsing_directives(Using_directivesContext context) { - transformToken(USING_DIRECTIVE, context.getStart()); - super.enterUsing_directives(context); - } - - @Override - public void enterClass_definition(Class_definitionContext context) { - transformToken(CLASS, context.getStart()); - super.enterClass_definition(context); - } - - @Override - public void enterClass_body(Class_bodyContext context) { - transformToken(CLASS_BEGIN, context.getStart()); - super.enterClass_body(context); - } - - @Override - public void exitClass_body(Class_bodyContext context) { - transformToken(CLASS_END, context.getStop()); - super.exitClass_body(context); - } - - @Override - public void enterMethod_declaration(Method_declarationContext context) { - transformToken(METHOD, context.getStart()); - super.enterMethod_declaration(context); - } - - @Override - public void enterMethod_body(Method_bodyContext context) { - transformToken(METHOD_BEGIN, context.getStart()); - super.enterMethod_body(context); - } - - @Override - public void exitMethod_body(Method_bodyContext context) { - transformToken(METHOD_END, context.getStop()); - super.exitMethod_body(context); - } - - @Override - public void enterProperty_declaration(Property_declarationContext context) { - transformToken(PROPERTY, context.getStart()); - super.enterProperty_declaration(context); - } - - @Override - public void enterEvent_declaration(Event_declarationContext context) { - transformToken(EVENT, context.getStart()); - super.enterEvent_declaration(context); - } - - @Override - public void enterIndexer_declaration(Indexer_declarationContext context) { - transformToken(INDEXER, context.getStart()); - super.enterIndexer_declaration(context); - } - - @Override - public void enterOperator_declaration(Operator_declarationContext context) { - transformToken(OPERATOR, context.getStart()); - super.enterOperator_declaration(context); - } - - @Override - public void enterConstructor_declaration(Constructor_declarationContext context) { - transformToken(CONSTRUCTOR, context.getStart()); - super.enterConstructor_declaration(context); - } - - @Override - public void enterDestructor_definition(Destructor_definitionContext context) { - transformToken(DESTRUCTOR, context.getStart()); - super.enterDestructor_definition(context); - } - - @Override - public void enterStruct_definition(Struct_definitionContext context) { - transformToken(STRUCT, context.getStart()); - super.enterStruct_definition(context); - } - - @Override - public void enterStruct_body(Struct_bodyContext context) { - transformToken(STRUCT_BEGIN, context.getStart()); - super.enterStruct_body(context); - } - - @Override - public void exitStruct_body(Struct_bodyContext context) { - transformToken(STRUCT_END, context.getStop()); - super.exitStruct_body(context); - } - - @Override - public void enterInterface_definition(Interface_definitionContext context) { - transformToken(INTERFACE, context.getStart()); - super.enterInterface_definition(context); - } - - @Override - public void enterInterface_body(Interface_bodyContext context) { - transformToken(INTERFACE_BEGIN, context.getStart()); - super.enterInterface_body(context); - } - - @Override - public void exitInterface_body(Interface_bodyContext context) { - transformToken(INTERFACE_END, context.getStart()); - super.exitInterface_body(context); - } - - @Override - public void enterEnum_definition(Enum_definitionContext context) { - transformToken(ENUM, context.getStart()); - super.enterEnum_definition(context); - } - - @Override - public void enterEnum_body(Enum_bodyContext context) { - transformToken(ENUM_BEGIN, context.getStart()); - super.enterEnum_body(context); - } - - @Override - public void exitEnum_body(Enum_bodyContext context) { - transformToken(ENUM_END, context.getStop()); - super.exitEnum_body(context); - } - - @Override - public void enterEnum_member_declaration(Enum_member_declarationContext context) { - transformToken(ENUMERAL, context.getStart()); - super.enterEnum_member_declaration(context); - } - - @Override - public void enterAttribute(AttributeContext context) { - transformToken(ATTRIBUTE, context.getStart()); - super.enterAttribute(context); - } - - @Override - public void enterDelegate_definition(Delegate_definitionContext context) { - transformToken(DELEGATE, context.getStart()); - super.enterDelegate_definition(context); - } - - @Override - public void enterUnsafeStatement(UnsafeStatementContext context) { - transformToken(UNSAFE, context.getStart()); - super.enterUnsafeStatement(context); - } - - @Override - public void enterFixedStatement(FixedStatementContext context) { - transformToken(FIXED, context.getStart()); - super.enterFixedStatement(context); - } - - @Override - public void enterAccessor_declarations(Accessor_declarationsContext context) { - transformToken(ACCESSORS_BEGIN, context.getStart()); - super.enterAccessor_declarations(context); - } - - @Override - public void exitAccessor_declarations(Accessor_declarationsContext context) { - transformToken(ACCESSORS_END, context.getStart()); - super.enterAccessor_declarations(context); - } - - @Override - public void enterAccessor_body(Accessor_bodyContext context) { - transformToken(ACCESSOR_BEGIN, context.getStart()); - super.enterAccessor_body(context); - } - - @Override - public void exitAccessor_body(Accessor_bodyContext context) { - transformToken(ACCESSOR_END, context.getStart()); - super.exitAccessor_body(context); - } - - @Override - public void enterConstant_declaration(Constant_declarationContext context) { - transformToken(CONSTANT, context.getStart()); - super.enterConstant_declaration(context); - } - - @Override - public void enterField_declaration(Field_declarationContext context) { - transformToken(FIELD, context.getStart()); - super.enterField_declaration(context); +public class CSharpListener extends AbstractAntlrListener { + public CSharpListener() { + visit(UsingNamespaceDirectiveContext.class).map(USING_DIRECTIVE); + visit(UsingAliasDirectiveContext.class, this::isAliasUsageAlsoImport).map(USING_DIRECTIVE); + visit(UsingStaticDirectiveContext.class).map(USING_DIRECTIVE); + + visit(Method_invocationContext.class).map(INVOCATION); + visit(Object_creation_expressionContext.class).map(OBJECT_CREATION); + visit(Array_initializerContext.class).map(ARRAY_CREATION); + visit(Assignment_operatorContext.class).map(ASSIGNMENT); + visit(IfStatementContext.class).map(IF); + visit(ELSE).map(IF); + visit(If_bodyContext.class).map(IF_BEGIN, IF_END); + visit(Switch_sectionContext.class).map(SWITCH_BEGIN, SWITCH_END); + visit(SwitchStatementContext.class).map(CASE); + + visit(DoStatementContext.class).map(LOOP_BEGIN, LOOP_END); + visit(WhileStatementContext.class).map(LOOP_BEGIN, LOOP_END); + visit(ForStatementContext.class).map(LOOP_BEGIN, LOOP_END); + visit(ForeachStatementContext.class).map(LOOP_BEGIN, LOOP_END); + + visit(BreakStatementContext.class).map(BREAK); + visit(ContinueStatementContext.class).map(CONTINUE); + visit(GotoStatementContext.class).map(GOTO); + + visit(ReturnStatementContext.class).map(RETURN); + visit(ThrowStatementContext.class).map(THROW); + + visit(CheckedStatementContext.class).map(CHECKED); + visit(CheckedExpressionContext.class).map(CHECKED); + visit(UncheckedStatementContext.class).map(UNCHECKED); + visit(UncheckedExpressionContext.class).map(UNCHECKED); + + visit(LockStatementContext.class).map(LOCK); + + visit(TryStatementContext.class).map(TRY); + visit(Specific_catch_clauseContext.class).map(CATCH); + visit(Finally_clauseContext.class).map(FINALLY); + + visit(Namespace_declarationContext.class).map(NAMESPACE); + visit(Namespace_bodyContext.class).map(NAMESPACE_BEGIN, NAMESPACE_END); + visit(Class_definitionContext.class).map(CLASS); + visit(Class_bodyContext.class, this::isClassBody).map(CLASS_BEGIN, CLASS_END); + visit(Method_declarationContext.class).map(METHOD); + visit(Method_bodyContext.class).map(METHOD_BEGIN, METHOD_END); + visit(Property_declarationContext.class).map(PROPERTY); + visit(Event_declarationContext.class).map(EVENT); + visit(Indexer_declarationContext.class).map(INDEXER); + visit(Operator_declarationContext.class).map(OPERATOR); + visit(BodyContext.class, this::isOperatorBody).map(METHOD_BEGIN, METHOD_END); + visit(Conversion_operator_declaratorContext.class).map(OPERATOR); + visit(BodyContext.class, this::isConversionOperatorBody).map(METHOD_BEGIN, METHOD_END); + visit(Constructor_declarationContext.class).map(CONSTRUCTOR); + visit(BodyContext.class, this::isConstructorBody).map(METHOD_BEGIN, METHOD_END); + visit(Destructor_definitionContext.class).map(DESTRUCTOR); + visit(Struct_definitionContext.class).map(STRUCT); + visit(Struct_bodyContext.class).map(STRUCT_BEGIN, STRUCT_END); + visit(Interface_definitionContext.class).map(INTERFACE); + visit(Class_bodyContext.class, this::isInterfaceBody).map(INTERFACE_BEGIN, INTERFACE_END); + visit(Enum_definitionContext.class).map(ENUM); + visit(Enum_bodyContext.class).map(ENUM_BEGIN, ENUM_END); + visit(Enum_member_declarationContext.class).map(ENUMERAL); + visit(AttributeContext.class).map(ATTRIBUTE); + visit(Delegate_definitionContext.class).map(DELEGATE); + visit(UnsafeStatementContext.class).map(UNSAFE); + visit(FixedStatementContext.class).map(FIXED); + visit(Accessor_declarationsContext.class).map(ACCESSORS_BEGIN, ACCESSORS_END); + visit(Accessor_bodyContext.class).map(ACCESSOR_BEGIN, ACCESSOR_END); + visit(Constant_declarationContext.class).map(CONSTANT); + visit(Field_declarationContext.class).map(FIELD); + visit(Local_variable_declarationContext.class).map(LOCAL_VARIABLE); + visit(Local_constant_declarationContext.class).map(LOCAL_VARIABLE); + + registerUnaryOperatorVisitors(); + } + + private void registerUnaryOperatorVisitors() { + visit(OP_DEC).map(ASSIGNMENT); + visit(OP_INC).map(ASSIGNMENT); + + visit(Shift_expressionContext.class, expr -> expr.additive_expression().size() == 2).map(ASSIGNMENT); + + visit(OP_ADD_ASSIGNMENT).map(ASSIGNMENT); + visit(OP_SUB_ASSIGNMENT).map(ASSIGNMENT); + visit(OP_AND_ASSIGNMENT).map(ASSIGNMENT); + visit(OP_DIV_ASSIGNMENT).map(ASSIGNMENT); + visit(OP_MOD_ASSIGNMENT).map(ASSIGNMENT); + visit(OP_OR_ASSIGNMENT).map(ASSIGNMENT); + visit(OP_XOR_ASSIGNMENT).map(ASSIGNMENT); + visit(OP_MULT_ASSIGNMENT).map(ASSIGNMENT); + visit(OP_COALESCING_ASSIGNMENT).map(ASSIGNMENT); + } + + private boolean isClassBody(ParserRuleContext context) { + return hasAncestor(context, Class_definitionContext.class, Interface_definitionContext.class); + } + + private boolean isInterfaceBody(ParserRuleContext context) { + return hasAncestor(context, Interface_definitionContext.class, Class_definitionContext.class); + } + + private boolean isConstructorBody(BodyContext context) { + return context.parent instanceof Constructor_declarationContext; + } + + private boolean isOperatorBody(BodyContext context) { + return context.parent instanceof Operator_declarationContext; + } + + private boolean isConversionOperatorBody(BodyContext context) { + if (!(context.parent instanceof Common_member_declarationContext parent)) { + return false; + } + + return parent.conversion_operator_declarator() != null; } - @Override - public void enterLocal_variable_declaration(Local_variable_declarationContext context) { - transformToken(LOCAL_VARIABLE, context.getStart()); - super.enterLocal_variable_declaration(context); + private boolean isAliasUsageAlsoImport(UsingAliasDirectiveContext context) { + Namespace_or_type_nameContext namespace = getDescendant(context, Namespace_or_type_nameContext.class); + + return namespace != null && (!namespace.DOT().isEmpty() && getDescendant(namespace, Type_argument_listContext.class) == null); } } 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..7d0b8951d 100644 --- a/languages/csharp/src/main/java/de/jplag/csharp/CSharpParserAdapter.java +++ b/languages/csharp/src/main/java/de/jplag/csharp/CSharpParserAdapter.java @@ -1,79 +1,37 @@ package de.jplag.csharp; -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.CharStreams; +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 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.TokenType; +import de.jplag.antlr.AbstractAntlrListener; +import de.jplag.antlr.AbstractAntlrParserAdapter; import de.jplag.csharp.grammar.CSharpLexer; import de.jplag.csharp.grammar.CSharpParser; /** * Parser adapter for the ANTLR 4 CSharp Parser and Lexer. It receives file to parse and passes them to the ANTLR * pipeline. Then it walks the produced parse tree and creates JPlag token with the {@link CSharpListener}. - * @author Timur Saglam */ -public class CSharpParserAdapter extends AbstractParser { - private List tokens; - private File currentFile; - - /** - * Creates the parser adapter. - */ - public CSharpParserAdapter() { - super(); +public class CSharpParserAdapter extends AbstractAntlrParserAdapter { + @Override + protected Lexer createLexer(CharStream input) { + return new CSharpLexer(input); } - /** - * Parses all tokens from a set of files. - * @param files is the set of files. - * @return the list of parsed tokens. - */ - 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 CSharpParser createParser(CommonTokenStream tokenStream) { + return new CSharpParser(tokenStream); } - private void parseFile(File file) throws ParsingException { - try (FileInputStream inputStream = new FileInputStream(file)) { - currentFile = file; - - // create a lexer, a parser and a buffer between them. - CSharpLexer lexer = new CSharpLexer(CharStreams.fromStream(inputStream)); - CommonTokenStream tokens = new CommonTokenStream(lexer); - CSharpParser parser = new CSharpParser(tokens); - - // Create a tree walker and the entry context defined by the parser grammar - ParserRuleContext entryContext = parser.compilation_unit(); - ParseTreeWalker treeWalker = new ParseTreeWalker(); - - // Walk over the parse tree: - for (int i = 0; i < entryContext.getChildCount(); i++) { - ParseTree parseTree = entryContext.getChild(i); - treeWalker.walk(new CSharpListener(this), parseTree); - } - } catch (IOException exception) { - throw new ParsingException(file, exception.getMessage(), exception); - } + @Override + protected ParserRuleContext getEntryContext(CSharpParser parser) { + return parser.compilation_unit(); } - /* package-private */ void addToken(TokenType type, int line, int column, int length) { - tokens.add(new Token(type, currentFile, line, column, length)); + @Override + protected AbstractAntlrListener getListener() { + return new CSharpListener(); } } 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..3895ed55e 100644 --- a/languages/csharp/src/main/java/de/jplag/csharp/CSharpTokenType.java +++ b/languages/csharp/src/main/java/de/jplag/csharp/CSharpTokenType.java @@ -17,10 +17,6 @@ public enum CSharpTokenType implements TokenType { SWITCH_BEGIN("SWITCH{"), SWITCH_END("}SWITCH"), CASE("CASE"), - DO("DO"), - WHILE("WHILE"), - FOR("FOR"), - FOREACH("FOREACH"), BREAK("BREAK"), CONTINUE("CONTINUE"), GOTO("GOTO"), @@ -29,10 +25,10 @@ public enum CSharpTokenType implements TokenType { CHECKED("CHECKED"), UNCHECKED("UNCHECKED"), LOCK("LOCK"), - USING("USING"), TRY("TRY"), CATCH("CATCH"), FINALLY("FINALLY"), + NAMESPACE("NAMESPACE"), NAMESPACE_BEGIN("NAMESPACE{"), NAMESPACE_END("}NAMESPACE"), USING_DIRECTIVE("USING"), @@ -67,10 +63,14 @@ public enum CSharpTokenType implements TokenType { ACCESSORS_BEGIN("ACCESSORS{"), ACCESSORS_END("}ACCESSORS"), ACCESSOR_BEGIN("ACCESSOR{"), - ACCESSOR_END("}ACCESSOR"); + ACCESSOR_END("}ACCESSOR"), + + LOOP_BEGIN("LOOP{"), + LOOP_END("}LOOP"); private final String description; + @Override public String getDescription() { return this.description; } diff --git a/languages/csharp/src/test/java/de/jplag/csharp/CSharpTest.java b/languages/csharp/src/test/java/de/jplag/csharp/CSharpTest.java new file mode 100644 index 000000000..2acbe4d98 --- /dev/null +++ b/languages/csharp/src/test/java/de/jplag/csharp/CSharpTest.java @@ -0,0 +1,56 @@ +package de.jplag.csharp; + +import static de.jplag.csharp.CSharpTokenType.ACCESSORS_BEGIN; +import static de.jplag.csharp.CSharpTokenType.ACCESSORS_END; +import static de.jplag.csharp.CSharpTokenType.ACCESSOR_BEGIN; +import static de.jplag.csharp.CSharpTokenType.ACCESSOR_END; +import static de.jplag.csharp.CSharpTokenType.ASSIGNMENT; +import static de.jplag.csharp.CSharpTokenType.CLASS; +import static de.jplag.csharp.CSharpTokenType.CLASS_BEGIN; +import static de.jplag.csharp.CSharpTokenType.CLASS_END; +import static de.jplag.csharp.CSharpTokenType.CONSTRUCTOR; +import static de.jplag.csharp.CSharpTokenType.FIELD; +import static de.jplag.csharp.CSharpTokenType.IF; +import static de.jplag.csharp.CSharpTokenType.IF_BEGIN; +import static de.jplag.csharp.CSharpTokenType.IF_END; +import static de.jplag.csharp.CSharpTokenType.INVOCATION; +import static de.jplag.csharp.CSharpTokenType.LOCAL_VARIABLE; +import static de.jplag.csharp.CSharpTokenType.METHOD; +import static de.jplag.csharp.CSharpTokenType.METHOD_BEGIN; +import static de.jplag.csharp.CSharpTokenType.METHOD_END; +import static de.jplag.csharp.CSharpTokenType.PROPERTY; +import static de.jplag.csharp.CSharpTokenType.RETURN; + +import de.jplag.testutils.LanguageModuleTest; +import de.jplag.testutils.datacollector.TestDataCollector; +import de.jplag.testutils.datacollector.TestSourceIgnoredLinesCollector; + +public class CSharpTest extends LanguageModuleTest { + public CSharpTest() { + super(new CSharpLanguage(), CSharpTokenType.class); + } + + @Override + protected void collectTestData(TestDataCollector collector) { + collector.testFile("TestClass.cs").testSourceCoverage().testTokenSequence(CLASS, CLASS_BEGIN, FIELD, CONSTRUCTOR, METHOD_BEGIN, + LOCAL_VARIABLE, METHOD_END, METHOD, METHOD_BEGIN, IF, IF_BEGIN, INVOCATION, IF_END, IF, IF_BEGIN, INVOCATION, IF_END, METHOD_END, + PROPERTY, ACCESSORS_BEGIN, ACCESSOR_BEGIN, ACCESSOR_END, ACCESSOR_BEGIN, ACCESSOR_END, ACCESSORS_END, FIELD, PROPERTY, + ACCESSORS_BEGIN, ACCESSOR_BEGIN, RETURN, ACCESSOR_END, ACCESSOR_BEGIN, ASSIGNMENT, ACCESSOR_END, ACCESSORS_END, CLASS_END); + + collector.testFile("AllInOneNoPreprocessor.cs").testSourceCoverage().testTokenCoverage(); + } + + @Override + protected void configureIgnoredLines(TestSourceIgnoredLinesCollector collector) { + collector.ignoreMultipleLines("/*", "*/"); + collector.ignoreLinesByPrefix("//"); + collector.ignoreLinesByRegex(".*//test-ignore"); + + // Using (import) as alias + collector.ignoreLinesByRegex("using.*=.*<.*>.*;"); + collector.ignoreLinesByRegex("using.*=[^.]+;"); + + collector.ignoreLinesByPrefix("extern"); + collector.ignoreByCondition(line -> line.trim().matches("[a-zA-Z0-9]+:.*")); + } +} diff --git a/languages/csharp/src/test/java/de/jplag/csharp/MinimalCSharpTest.java b/languages/csharp/src/test/java/de/jplag/csharp/MinimalCSharpTest.java deleted file mode 100644 index 5f8a3135e..000000000 --- a/languages/csharp/src/test/java/de/jplag/csharp/MinimalCSharpTest.java +++ /dev/null @@ -1,75 +0,0 @@ -package de.jplag.csharp; - -import static de.jplag.csharp.CSharpTokenType.ACCESSORS_BEGIN; -import static de.jplag.csharp.CSharpTokenType.ACCESSORS_END; -import static de.jplag.csharp.CSharpTokenType.ACCESSOR_BEGIN; -import static de.jplag.csharp.CSharpTokenType.ACCESSOR_END; -import static de.jplag.csharp.CSharpTokenType.ASSIGNMENT; -import static de.jplag.csharp.CSharpTokenType.CLASS; -import static de.jplag.csharp.CSharpTokenType.CLASS_BEGIN; -import static de.jplag.csharp.CSharpTokenType.CLASS_END; -import static de.jplag.csharp.CSharpTokenType.CONSTRUCTOR; -import static de.jplag.csharp.CSharpTokenType.FIELD; -import static de.jplag.csharp.CSharpTokenType.IF; -import static de.jplag.csharp.CSharpTokenType.IF_BEGIN; -import static de.jplag.csharp.CSharpTokenType.IF_END; -import static de.jplag.csharp.CSharpTokenType.INVOCATION; -import static de.jplag.csharp.CSharpTokenType.LOCAL_VARIABLE; -import static de.jplag.csharp.CSharpTokenType.METHOD; -import static de.jplag.csharp.CSharpTokenType.METHOD_BEGIN; -import static de.jplag.csharp.CSharpTokenType.METHOD_END; -import static de.jplag.csharp.CSharpTokenType.PROPERTY; -import static de.jplag.csharp.CSharpTokenType.RETURN; -import static org.junit.jupiter.api.Assertions.assertEquals; -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.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; -import de.jplag.TokenType; - -class MinimalCSharpTest { - private final Logger logger = LoggerFactory.getLogger(MinimalCSharpTest.class); - - private static final Path BASE_PATH = Path.of("src", "test", "resources", "de", "jplag", "csharp"); - private static final String TEST_SUBJECT = "TestClass.cs"; - - private de.jplag.Language language; - private File baseDirectory; - - @BeforeEach - public void setUp() { - language = new Language(); - baseDirectory = BASE_PATH.toFile(); - assertTrue(baseDirectory.exists(), "Could not find base directory!"); - } - - @Test - void testParsingTestClass() throws ParsingException { - List expectedToken = List.of(CLASS, CLASS_BEGIN, FIELD, CONSTRUCTOR, LOCAL_VARIABLE, METHOD, METHOD_BEGIN, IF, IF_BEGIN, - INVOCATION, IF_END, IF_BEGIN, INVOCATION, IF_END, METHOD_END, PROPERTY, ACCESSORS_BEGIN, ACCESSOR_BEGIN, ACCESSOR_END, ACCESSOR_BEGIN, - ACCESSOR_END, ACCESSORS_END, FIELD, PROPERTY, ACCESSORS_BEGIN, ACCESSOR_BEGIN, RETURN, ACCESSOR_END, ACCESSOR_BEGIN, ASSIGNMENT, - ACCESSOR_END, ACCESSORS_END, CLASS_END, SharedTokenType.FILE_END); - - // Parse test input - List result = language.parse(Set.of(new File(baseDirectory, TEST_SUBJECT))); - logger.info(TokenPrinter.printTokens(result, baseDirectory)); - - // Compare parsed tokens: - assertEquals(expectedToken.size(), result.size()); - List actualToken = result.stream().map(Token::getType).toList(); - assertEquals(expectedToken, actualToken); - } - -} diff --git a/languages/csharp/src/test/resources/de/jplag/csharp/AllInOneNoPreprocessor.cs b/languages/csharp/src/test/resources/de/jplag/csharp/AllInOneNoPreprocessor.cs new file mode 100644 index 000000000..b819b136b --- /dev/null +++ b/languages/csharp/src/test/resources/de/jplag/csharp/AllInOneNoPreprocessor.cs @@ -0,0 +1,1050 @@ +//From https://github.com/antlr/grammars-v4/tree/master/csharp/examples + +extern alias Foo; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using M = System.Math; + +using ConsoleApplication2.Test; + +/**/ +/* the previous comment is an empty delimited comment and not a document comment */ +/** this is a document comment */ +// this one is a single line comment + +using X = int1; +using Y = ABC.X; + +using static System.Math; +using static System.DayOfWeek; +using static System.Linq.Enumerable; + +[assembly: System.Copyright(@"(C)""2009")] +[module: System.Copyright("\n\t\u0123(C) \"2009" + "\u0123")] + +class TopLevelType : IDisposable +{ + void IDisposable.Dispose() { } +} + +namespace My +{ + using A.B; + + interface CoContra { } + delegate void CoContra2<[System.Obsolete()] out T, in K> () where T : struct; + + public unsafe partial class A : C, I + { + [DllImport("kernel32", SetLastError = true)] + static extern bool CreateDirectory(string name, SecurityAttribute sa); + + private const int global = int.MinValue - 1; + + static A() + { + } + + [method: Obsolete] + public A([param: Obsolete] int foo) : base(1) { + L: { //test-ignore + int i = sizeof(int); + ++i; + var s1 = $"x {1 , -2 :d}"; + var s2 = $@"x {1 , -2 :d}"; + } //test-ignore + + + Console.WriteLine(export.iefSupplied.command); + + const int? local = int.MaxValue; + const Guid? local0 = new Guid(r.ToString()); + + var ะฟั€ะธะฒะตั‚ = local; + var ะผะธั€ = local; + int local3 = 0, local4 = 1; + local3 = local4 = 1; + var local5 = null as Action ?? null; + var local6 = local5 is Action; + + var u = 1u; + var U = 1U; + long hex = 0xBADC0DE, Hex = 0XDEADBEEF, l = -1L, L = 1L, l2 = 2l; + ulong ul = 1ul, Ul = 1Ul, uL = 1uL, UL = 1UL, lu = 1lu, Lu = 1Lu, lU = 1lU, LU = 1LU; + int minInt32Value = -2147483648; + int minInt64Value = -9223372036854775808L; + + bool @bool; + byte @byte; + char @char = 'c', \u0066 = '\u0066', hexchar = '\x0130', hexchar2 = (char)0xBAD; + string \U00000065 = "\U00000065"; + decimal @decimal = 1.44M; + @decimal = 1.2m; + dynamic @dynamic; + double @double = M.PI; + @double = 1d; + @double = 1D; + @double = -1.2e3; + float @float = 1.2f; + @float = 1.44F; + int @int = local ?? -1; + long @long; + object @object; + sbyte @sbyte; + short @short; + string @string = @"""/*"; + uint @uint; + ulong @ulong; + ushort @ushort; + + dynamic dynamic = local5; + var add = 0; + var alias = 0; + var arglist = 0; + var ascending = 0; + var async = 0; + var await = 0; + var by = 0; + var descending = 0; + var dynamic = 0; + var equals = 0; + var from = 0; + var get = 0; + var group = 0; + var into = 0; + var join = 0; + var let = 0; + var nameof = 0; + var on = 0; + var orderby = 0; + var partial = 0; + var remove = 0; + var select = 0; + var set = 0; + var var = 0; + var when = 0; + var where = 0; + var yield = 0; + var __ = 0; + where = yield = 0; + + if (i > 0) + { + return; + } + else if (i == 0) + { + throw new Exception(); + } + var o1 = new MyObject(); + var o2 = new MyObject(var); + var o3 = new MyObject { A = i }; + var o4 = new MyObject(@dynamic) + { A = 0, B = 0, C = 0 };//test-ignore + var o5 = new { A = 0 }; + var dictionaryInitializer = new Dictionary + { //test-ignore + {1, ""}, //test-ignore + {2, "a"} //test-ignore + };//test-ignore + float[] a = new float[] + { 0f, 1.1f };//test-ignore + int[, ,] cube = { { { 111, 112, }, { 121, 122 } }, { { 211, 212 }, { 221, 222 } } }; + int[][] jagged = { { 111 }, { 121, 122 } }; + int[][,] arr = new int[5][,]; // as opposed to new int[][5,5] + arr[0] = new int[5,5]; // as opposed to arr[0,0] = new int[5]; + arr[0][0,0] = 47; + int[] arrayTypeInference = new[] { 0, 1, }; + switch (3) { } + switch (i) + {//test-ignore + case 0: case 1: + {//test-ignore + goto case 2; + }//test-ignore + case 2 + 3: + {//test-ignore + goto default; + break; + }//test-ignore + default: + {//test-ignore + return; + }//test-ignore + }//test-ignore + while (i < 10) { + ++i; + if (true) continue; + break; + } + do { + ++i; + if (true) continue; + break; + } while (i < 10); + for (int j = 0; j < 100; ++j) { + for(;;) { + for (int i = 0, j = 0; i < length; i++, j++) { } + if (true) continue; + break; + } + } + label: + goto label; + label2: ; + foreach (var i in Items()) { + if (i == 7) + return; + else + continue; + } + checked + {//test-ignore + checked(++i); + }//test-ignore + unchecked + {//test-ignore + unchecked(++i); + }//test-ignore + lock (sync) + process(); + using (var v = BeginScope()) + using (A a = new A()) + using (A a = new A(), b = new A()) + using (BeginScope()) + return; + yield return this.items[3];//test-ignore + yield break; //test-ignore + fixed (int* p = stackalloc int[100], q = &y) + { //test-ignore + *intref = 1; + } //test-ignore + fixed (int* p = stackalloc int[100]) + { //test-ignore + *intref = 1; + } //test-ignore + unsafe + { //test-ignore + int* p = null; + } //test-ignore + try + { //test-ignore + throw null; + } //test-ignore + catch (System.AccessViolationException av) + { //test-ignore + throw av; + } //test-ignore + catch (Exception) + { //test-ignore + throw; + } //test-ignore + finally + { //test-ignore + try { } catch { } + } //test-ignore + var anonymous = + { + A = 1, + B = 2, + C = 3, + }; //test-ignore + var query = from c in customers + let d = c//test-ignore + where d != null//test-ignore + join c1 in customers on c1.GetHashCode() equals c.GetHashCode() + join c1 in customers on c1.GetHashCode() equals c.GetHashCode() into e + group c by c.Country//test-ignore + into g //test-ignore + orderby g.Count() ascending + orderby g.Key descending //test-ignore + select new { Country = g.Key, CustCount = g.Count() }; + query = from c in customers + select c into d//test-ignore + select d;//test-ignore + } + ~A() + { //test-ignore + } //test-ignore + private readonly int f1; + [Obsolete] + [NonExisting] + [Foo::NonExisting(var, 5)] + [CLSCompliant(false)] + [Obsolete, System.NonSerialized, NonSerialized, CLSCompliant(true || false & true)] + private volatile int f2; + [return: Obsolete] + [method: Obsolete] + public void Handler(object value) + { + } + public int m(T t) where T : class, new() + { + base.m(t); + return 1; + } + public string P + { //test-ignore + get + { + return "A"; + } + set; + } //test-ignore + public abstract string P + { //test-ignore + get; + } //test-ignore + public abstract int this[int index] + { //test-ignore + protected internal get; + internal protected set; + } //test-ignore + [method: Obsolete] + [field: Obsolete] + [event: Obsolete] + public readonly event Event E; + [event: Test] + public event Action E1 + { //test-ignore + [Obsolete] + add { value = value; } + [Obsolete] + [return: Obsolete] + remove { E += Handler; E -= Handler; } + } //test-ignore + public static A operator +(A first, A second) + { + Delegate handler = new Delegate(Handler); + return first.Add(second); + } + [method: Obsolete] + [return: Obsolete] + public static bool operator true(A a) + { + return true; + } + public static bool operator false(A a) + { + return false; + } + class C + { + } + } + public struct S : I + { + public S() + { + } + private int f1; + [Obsolete("Use Script instead", error: false)] + private volatile int f2; + public abstract int m(T t) where T : struct + { + return 1; + } + public string P + { //test-ignore + get + { + int value = 0; + return "A"; + } + set; + } //test-ignore + public abstract string P + { //test-ignore + get; + } //test-ignore + public abstract int this[int index] + { //test-ignore + get; + internal protected set; + } //test-ignore + public event Event E; + public static A operator +(A first, A second) + { + return first.Add(second); + } + fixed int field[10];//test-ignore + class C + { + } + } + public interface I + { + void A(int value); + string Value + { //test-ignore + get; + set; + } //test-ignore + unsafe void UpdateSignatureByHashingContent([In]byte* buffer, int size); + } + [type: Flags] + public enum E + { + A, + B = A, + C = 2 + A, + D, + } + + public delegate void Delegate(object P); + namespace Test + { + using System; + using System.Collections; + public class ะกะฟะธัะพะบ + { + public static IEnumerable Power(int number, int exponent) + { + ะกะฟะธัะพะบ ะกะฟะธัะพะบ = new ะกะฟะธัะพะบ(); + ะกะฟะธัะพะบ.Main(); + int counter = (0 + 0); + int ืืชืจ = 0; + while (++counter++ < --exponent--) { + result = result * number + +number+++++number; + yield return result;//test-ignore + } + } + static void Main() + { + foreach (int i in Power(2, 8)) + { //test-ignore + Console.Write("{0} ", i); + } + } + async void Wait() + { + await System.Threading.Tasks.Task.Delay(0); + } + void AsyncAnonymous() // C # 5 feature + { + var task = Task.Factory.StartNew(async () => + { //test-ignore + return await new WebClient().DownloadStringTaskAsync("http://example.com"); + }); //test-ignore + } + } + } +} + +namespace ConsoleApplication1 +{ + namespace RecursiveGenericBaseType + { + class A : B, A> where T : A + { + protected virtual A M() { } + protected abstract B, A> N() { } + static B, A> O() { } + } + + sealed class B : A> + { + protected override A M() { } + protected sealed override B, A> N() { } + new static A O() { } + } + } + + namespace Boo + { + public class Bar where T : IComparable + { + public T f; + public class Foo : IEnumerable + { + public void Method(K k, T t, U u) + where K : IList, IList, IList //test-ignore + where V : IList //test-ignore + { + A a; + M(A(5)); + } + }; + }; + }; + + class Test + { + void Bar3() + { + var x = new Boo.Bar.Foo(); + x.Method(" ", 5, new object()); + + var q = from i in new int[] { 1, 2, 3, 4 } + where i > 5//test-ignore + select i;//test-ignore + } + + public static implicit operator Test(string s) + { + return new ConsoleApplication1.Test(); + } + public static explicit operator Test(string s = "") + { + return new Test(); + } + + public int foo = 5; + void Bar2() + { + foo = 6; + this.Foo = 5.GetType(); Test t = "sss"; + } + + public event EventHandler MyEvent = delegate { }; + + void Blah() + { + int i = 5; + int? j = 6; + + Expression> e = () => i; + Expression> e2 = b => () => { return; }; + Func f = async delegate (bool a) + { //test-ignore + return await !a; + }; //test-ignore + Func f2 = (a, b) => 0; + f2 = (int a, int b) => 1; + Action a = Blah; + f2 = () => {}; + f2 = () => {;}; + } + + delegate Recursive Recursive(Recursive r); + delegate Recursive Recursive(Recursive r); + + public Type Foo { + [Obsolete("Name", error = false)] + get//test-ignore + { + var result = typeof(IEnumerable); + var t = typeof(int?) == typeof(Nullable); + t = typeof(IEnumerable); + return typeof(IEnumerable<>); + } + set//test-ignore + { + var t = typeof(System.Int32); + t.ToString(); + t = value; + } + }//test-ignore + + public void Constants() + { + int i = 1 + 2 + 3 + 5; + global::System.String s = "a" + (System.String)"a" + "a" + "a" + "a" + "A"; + } + + public void ConstructedType() + { + List i = null; + int c = i.Count; + } + } +} + +namespace Comments.XmlComments.UndocumentedKeywords +{ + /// + /// Whatever + /// + /// + /// // + /// /* */ + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + class /*///*/C + { + void M(T t, U u) + { + // comment + /* *** / */ + /* // + */ + /*s*///comment + // /***/ + /*s*/int /*s*/intValue = 0; + intValue = intValue /*s*/+ 1; + string strValue = /*s*/"hello"; + /*s*/MyClass c = new MyClass(); + string verbatimStr = /*s*/@"\\\\"; + } + } + + //General Test F. Type a very long class name, verify colorization happens correctly only upto the correct size (118324) + class TestClassXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/*Scen8*/{ } + + class TestClassXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX22/*Scen9*/{ } + + class yield + { + void Foo(__arglist) + { + C c = null; + c.M(5, default(U)); + TypedReference tr = __makeref(c); + Type t = __reftype(tr); + int j = __refvalue(tr, int); + Params(a: t, b: t); + Params(ref c, out c); + } + void Params(ref dynamic a, out dynamic b, params dynamic[] c) {} + void Params(out dynamic a = 2, ref dynamic c = default(dynamic), params dynamic[][] c) {} + + public override string ToString() { return base.ToString(); } + + public partial void OnError(); + + public partial void method() + { + int?[] a = new int?[5];/*[] bug*/ // YES [] + int[] var = { 1, 2, 3, 4, 5 };/*,;*/ + int i = a[i];/*[]*/ + Foo f = new Foo();/*<> ()*/ + f.method();/*().*/ + i = i + i - i * i / i % i & i | i ^ i;/*+ - * / % & | ^*/ + bool b = true & false | true ^ false;/*& | ^*/ + b = !b;/*!*/ + i = ~i;/*~i*/ + b = i < i && i > i;/*< && >*/ + int? ii = 5;/*? bug*/ // NO ? + int f = true ? 1 : 0;/*? :*/ // YES : + i++;/*++*/ + i--;/*--*/ + b = true && false || true;/*&& ||*/ + i << 5;/*<<*/ + i >> 5;/*>>*/ + b = i == i && i != i && i <= i && i >= i;/*= == && != <= >=*/ + i += 5.0;/*+=*/ + i -= i;/*-=*/ + i *= i;/**=*/ + i /= i;/*/=*/ + i %= i;/*%=*/ + i &= i;/*&=*/ + i |= i;/*|=*/ + i ^= i;/*^=*/ + i <<= i;/*<<=*/ + i >>= i;/*>>=*/ + object s = x => x + 1;/*=>*/ + double d = .3; + Point point; + unsafe + {//test-ignore + Point* p = &point;/** &*/ + p->x = 10;/*->*/ + }//test-ignore + IO::BinaryReader br = null; + x[i: 1] = 3; + x[i: 1, j: 5] = "str"; + } + + struct Point { public int X; public int Y; public void ThisAccess() { this = this; } } + } + + // From here:https://github.com/dotnet/roslyn/wiki/New-Language-Features-in-C%23-6 + class CSharp6Features + { + // Initializers for auto-properties + public string First { get; set; } = "Jane"; + public string Last { get; set; } = "Doe"; + + // Getter-only auto-properties + public string Third { get; } = "Jane"; + public string Fourth { get; } = "Doe"; + + // Expression bodies on method-like members + public Point Move(int dx, int dy) => new Point(x + dx, y + dy); + public static Complex operator +(Complex a, Complex b) => a.Add(b); + public static implicit operator string(Person p) => p.First + " " + p.Last; + public void Print() => Console.WriteLine(First + " " + Last); + + // Expression bodies on property-like function members + public string Name => First + " " + Last; + public int this[long id] => id; + + async void Test() + { + // Using static + WriteLine(Sqrt(3*3 + 4*4)); + WriteLine(Friday - Monday); + var range = Range(5, 17); // Ok: not extension + var even = range.Where(i => i % 2 == 0); // Ok + + // Null-conditional operators + int? length = customers?.Length; // null if customers is null + Customer first = customers?[0]; // null if customers is null + int length = customers?.Length ?? 0; // 0 if customers is null + int? first = customers?[0]?.Orders?.Count(); + PropertyChanged?.Invoke(this, args); + + // String interpolation + string s = $"{p.Name, 20} is {p.Age:D3} year{{s}} old #"; + s = $"{p.Name} is \"{p.Age} year{(p.Age == 1 ? "" : "s")} old"; + s = $"{(p.Age == 2 ? $"{new Person { } }" : "")}"; + s = $@"\{p.Name} + ""\"; //test-ignore + s = $"Color [ R={func(b: 3):#0.##}, G={G:#0.##}, B={B:#0.##}, A={A:#0.##} ]"; + + // nameof expressions + if (x == null) + throw new ArgumentNullException(nameof(x)); + WriteLine(nameof(person.Address.ZipCode)); // prints "ZipCode" + + // Index initializers + var numbers = new Dictionary { + [7] = "seven", //test-ignore + [9] = "nine", //test-ignore + [13] = "thirteen" //test-ignore + }; //test-ignore + + // Exception filters + try {} + catch (MyException e) when (myfilter(e)) + { } //test-ignore + + // Await in catch and finally blocks + Resource res = null; + try + { //test-ignore + res = await Resource.OpenAsync(); // You could do this. + } //test-ignore + catch(ResourceException e) + { //test-ignore + await Resource.LogAsync(res, e); // Now you can do this โ€ฆ + } //test-ignore + finally + { //test-ignore + if (res != null) + await res.CloseAsync(); // โ€ฆ and this. + } //test-ignore + } + } +} + +class CSharp70 +{ + void PatternMatching(string arg, int b) + { + switch (arg) + { //test-ignore + case "A" when b > 50: + case "B" when b < 50: //test-ignore + default: + break; + } //test-ignore + + (A D, E H) = e; + + if (x?.y?.z is Type value2) + { + // code using value + } + + if (expr is Type v) { Hello(); } + } + + public static async Task LocalFunctions(string[] args) + { + string Hello2(int i) //test-ignore + { //test-ignore + return args[i]; + } //test-ignore + + async Task Hello(T i) => await Task.FromResult(args[i]); + await Hello(1); + } + + public static void OutVar(string[] args) + { + int.TryParse(Hello(1), out var item); + int.TryParse(Hello(1), out int item); + } + + public void ThrowExpression() + { + var result = nullableResult ?? throw new NullReferenceException(); + } + + public void BinaryLiterals() + { + int nineteen = 0b10011; + } + + public void DigitSeparators() + { + int bin = 0b1001_1010_0001_0100; + int hex = 0x1b_a0_44_fe; + int dec = 33_554_432; + int weird = 1_2__3___4____5_____6______7_______8________9; + double real = 1_000.111_1e-1_000; + } +} + +class CSharp71 +{ + void DefaultWithoutTypeName(string content = default) + { + DefaultWithoutTypeName(default); + } + + void TupleRecognize(int a, (int, int) b, (int, int, int)? c) + { + var result = list.Select(c => (c.f1, f3: c.f2)).Where(t => t.f2 == 1); + } +} + +class CSharp72 +{ + readonly struct ReadonlyRef1 + { + Func s = (in int x) => x; + ref TValue this[in TKey index] => null; + public static Vector3 operator+(in Vector3 x, in Vector3 y) => null; + + static readonly ref Vector3 M1_Trace() + { + // OK + ref readonly var r1 = ref M1(); + + // Not valid. Need an LValue + ref readonly Vector3 r2 = ref default(Vector3); + + // Not valid. r1 is readonly. + Mutate(ref r1); + + // OK. + Print(in r1); + + // OK. + return ref r1; + } + } + + ref struct ReadonlyRef2 + { + ref readonly Guid Test(in Vector3 v1, in Vector3 v2) + { + // not OK!! + v1 = default(Vector3); + + // not OK!! + v1.X = 0; + + // not OK!! + foo(ref v1.X); + + return ref (arr != null ? ref arr[0]: ref otherArr[0]); + + Span span = stackalloc int[1]; + + // OK + return new Vector3(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z); + } + + ref T Choice(bool condition, ref T consequence, ref T alternative) + { + if (condition) + { + return ref consequence; + } + else + { + return ref alternative; + } + } + } + + public void DoSomething(bool isEmployed, string personName, int personAge) { } + + public void NonTrailingNamedArguments() + { + DoSomething(isEmployed:true, name, age); // currently CS1738, but would become legal + DoSomething(true, personName:name, age); // currently CS1738, but would become legal + DoSomething(name, isEmployed:true, age); // remains illegal + DoSomething(name, age, isEmployed:true); // remains illegal + DoSomething(true, personAge:age, personName:name); // already legal + } + + public void ConditionalRef() + { + ref var r = ref (arr != null ? ref arr[0]: ref otherArr[0]); + } + + public void LeadingSeparator() + { + var res = 0 + + 123 // permitted in C# 1.0 and later //test-ignore + + 1_2_3 // permitted in C# 7.0 and later //test-ignore + + 0x1_2_3 // permitted in C# 7.0 and later //test-ignore + + 0b101 // binary literals added in C# 7.0 //test-ignore + + 0b1_0_1 // permitted in C# 7.0 and later //test-ignore + + // in C# 7.2, _ is permitted after the `0x` or `0b` + + 0x_1_2 // permitted in C# 7.2 and later //test-ignore + + 0b_1_0_1 // permitted in C# 7.2 and later //test-ignore + ; //test-ignore + } +} + +class CSharp73 +{ + void Blittable(T value) where T : unmanaged + { //test-ignore + var unmanaged = 666; + } //test-ignore + + unsafe struct IndexingMovableFixed + { + public fixed int myFixedField[10]; //test-ignore + } + + static IndexingMovableFixed s; + + public unsafe void IndexingMovableFixedFields() + { + int* ptr = s.myFixedField; + int t = s.myFixedField[5]; + } + + public void PatternBasedFixed() + { + fixed(byte* ptr = byteArray) + { //test-ignore + // ptr is a native pointer to the first element of the array + // byteArray is protected from being moved/collected by the GC for the duration of this block + } //test-ignore + } + + public void StackallocArrayInitializer() + { + Span a = stackalloc int[3]; // currently allowed + Span a = stackalloc int[3] { 1, 2, 3 }; + Span a = stackalloc int[] { 1, 2, 3 }; + Span a = stackalloc[] { 1, 2, 3 }; + } + + public void TupleEquality() + { + (int, (int, int)) t1, t2; + var res = t1 == (1, (2, 3)); + } +} + +namespace CSharp80 +{ + class CSharp80ExceptInterfaceDefaultImplement + { + void ReferenceNullable() + { + var? x = E; + x!.ToString(); + string? wtf = null; + int?[]? hello; + } + + void Patterns() + { + if (o is string { Length: 5 } s) Do(); + + return lang.CountOfTokens switch + { //test-ignore + 1 => 100, //test-ignore + 2 => 200, //test-ignore + _ => throw new global::System.Exception() + }; //test-ignore + + var newState = (GetState(), action, hasKey) switch + { //test-ignore + (DoorState.Closed, Action.Open, _) => DoorState.Opened, //test-ignore + (DoorState.Opened, Action.Close, _) => DoorState.Closed, //test-ignore + (DoorState.Closed, Action.Lock, true) => DoorState.Locked, //test-ignore + (DoorState.Locked, Action.Unlock, true) => DoorState.Closed, //test-ignore + (var state, _, _) => state //test-ignore + }; //test-ignore + } + + async Task AsyncStreams() + { + await foreach (var item in asyncEnumerables) + { //test-ignore + } + } + + void Ranges() + { + var thirdItem = list[2]; // list[2] + var lastItem = list[^1]; // list[Index.CreateFromEnd(1)] + var multiDimensional = list[3, ^2]; // list[3, Index.CreateFromEnd(2)] + + var slice1 = list[2..^3]; // list[Range.Create(2, Index.CreateFromEnd(3))] + var slice2 = list[..^3]; // list[Range.ToEnd(Index.CreateFromEnd(3))] + var slice3 = list[2..]; // list[Range.FromStart(2)] + var slice4 = list[..]; // list[Range.All] + var multiDimensional = list[1..2, ..]; // list[Range.Create(1, 2), Range.All] + } + + void UsingDeclarators() + { + using var item = new FileStream("./.f"); + fixed char* ch = "hell"; + item.Dispose(); // no! + } + + void StaticLocalFunction() + { + static unsafe void Func1() {} //test-ignore + static unsafe void Func1() {} //test-ignore + async static void Func2() {} //test-ignore + static async void Func2() {} //test-ignore + } + + void NullCoalescingAssignment() + { + var item = a ??= b ??= c ??= d ??= throw new Exception(); + } + + public readonly float Hello() + { + return 0.1f; + } + } + + interface IA + { + void M() { WriteLine("IA.M"); } + } + + interface IA + { + void M() { WriteLine("IA.M"); } + } + + interface IB : IA + { + override void IA.M() { WriteLine("IB.M"); } // explicitly named + } + + interface IC : IA + { + override void M() { WriteLine("IC.M"); } // implicitly named + } +} diff --git a/languages/csharp/src/test/resources/de/jplag/csharp/TestClass.cs b/languages/csharp/src/test/resources/de/jplag/csharp/TestClass.cs index 4188cd3cb..3b6a4bd14 100644 --- a/languages/csharp/src/test/resources/de/jplag/csharp/TestClass.cs +++ b/languages/csharp/src/test/resources/de/jplag/csharp/TestClass.cs @@ -15,8 +15,7 @@ public void MyMethod(int parameter1, string parameter2) if(parameter1 == 0) { Console.WriteLine("Second parameter {0}", parameter2); } else { - Console.WriteLine("First Parameter {0}, second parameter {1}", - parameter1, parameter2); + Console.WriteLine("First Parameter {0}, second parameter {1}", parameter1, parameter2); } } @@ -26,8 +25,8 @@ public void MyMethod(int parameter1, string parameter2) private int myPropertyVar; public int MyProperty - { + {//test-ignore get { return myPropertyVar; } set { myPropertyVar = value; } - } + }//test-ignore } \ No newline at end of file diff --git a/languages/emf-metamodel-dynamic/README.md b/languages/emf-metamodel-dynamic/README.md index 45ef1142a..0502cfac5 100644 --- a/languages/emf-metamodel-dynamic/README.md +++ b/languages/emf-metamodel-dynamic/README.md @@ -1,5 +1,5 @@ # Dynamic EMF metamodel language module -The dynamic EMF metamodel language module allows the use of JPlag with metamodel submissions. +The dynamic EMF metamodel language module allows the use of JPlag with EMF metamodel submissions. It is based on the EMF API. ### EMF specification compatibility @@ -9,8 +9,14 @@ 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). +Note that this language module is currently not offered via the CLI. +Use the non-dymamic version instead (`-l emf`). -### 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). -A short summary can be found on [Kudos](https://www.growkudos.com/publications/10.1145%25252F3550356.3556508/reader). +### Report Viewer +In the report viewer, Emfatic is used as a textual model view. + +### Literature +* [*"Token-based Plagiarism Detection for Metamodels" (MODELS-C'22)*](https://dl.acm.org/doi/10.1145/3550356.3556508). +* Its [Kudos Summary](https://www.growkudos.com/publications/10.1145%25252F3550356.3556508/reader). +* [*"Token-based Plagiarism Detection for Metamodels" (MODELS-C'22)*] +* *"Automated Detection of AI-Obfuscated Plagiarism in Modeling Assignments" (ICSE-SEET'24)* 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..e3ee69097 --- /dev/null +++ b/languages/emf-metamodel-dynamic/src/main/java/de/jplag/emf/dynamic/parser/DynamicElementTokenizer.java @@ -0,0 +1,31 @@ +package de.jplag.emf.dynamic.parser; + +import java.util.LinkedHashSet; +import java.util.SequencedSet; + +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 static final SequencedSet knownTokenTypes = new LinkedHashSet<>(); + + @Override + public TokenType element2Token(EObject modelElement) { + DynamicMetamodelTokenType token = new DynamicMetamodelTokenType(modelElement); + knownTokenTypes.add(token); + return token; + } + + @Override + public SequencedSet allTokenTypes() { + return new LinkedHashSet<>(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..a437be6e2 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 result = language.parse(new HashSet<>(testFiles), true); 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..071bfbcaf 100644 --- a/languages/emf-metamodel/README.md +++ b/languages/emf-metamodel/README.md @@ -1,5 +1,5 @@ # EMF metamodel language module -The EMF metamodel language module allows the use of JPlag with metamodel submissions. +The EMF metamodel language module allows the use of JPlag with EMF metamodel submissions. It is based on the EMF API. ### EMF specification compatibility @@ -9,8 +9,14 @@ 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). +The input for this module is a set of EMF metamodels (`.ecore` files). +To use this module, add the `-l emf` 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). -A short summary can be found on [Kudos](https://www.growkudos.com/publications/10.1145%25252F3550356.3556508/reader). +### Report Viewer +In the report viewer, Emfatic is used as a textual model view. + +### Literature +* [*"Token-based Plagiarism Detection for Metamodels" (MODELS-C'22)*](https://dl.acm.org/doi/10.1145/3550356.3556508). +* Its [Kudos Summary](https://www.growkudos.com/publications/10.1145%25252F3550356.3556508/reader). +* [*"Token-based Plagiarism Detection for Metamodels" (MODELS-C'22)*] +* *"Automated Detection of AI-Obfuscated Plagiarism in Modeling Assignments" (ICSE-SEET'24)* 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 83% 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..fac48399f 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; } @@ -55,8 +55,8 @@ public int minimumTokenMatch() { } @Override - public List parse(Set files) throws ParsingException { - return parser.parse(files); + public List parse(Set files, boolean normalize) throws ParsingException { + return parser.parse(files, normalize); } @Override 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..0e40f976d --- /dev/null +++ b/languages/emf-metamodel/src/main/java/de/jplag/emf/normalization/ContainmentOrderNormalizer.java @@ -0,0 +1,136 @@ +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; + } + if (firstType == null) { + return -1; + } + 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; + } + + /** + * Calculates the euclidean distance for two token occurrence vectors. As they are zero-padded, they are virtually of + * the same length. + */ + private static double euclideanDistance(TokenOccurenceVector first, TokenOccurenceVector second) { + 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/TokenOccurenceVector.java b/languages/emf-metamodel/src/main/java/de/jplag/emf/normalization/TokenOccurenceVector.java new file mode 100644 index 000000000..47c2c0dbb --- /dev/null +++ b/languages/emf-metamodel/src/main/java/de/jplag/emf/normalization/TokenOccurenceVector.java @@ -0,0 +1,39 @@ +package de.jplag.emf.normalization; + +import java.util.List; + +/** + * A vector for the occurrence frequency of different token types. The vector is padded with zeroes beyond its original + * size. The vector content cannot be changed after its creation. + */ +public class TokenOccurenceVector { + private final List originalVector; + + /** + * Creates a zero-padded token occurrence vector. + * @param originalVector specifies the occurrence frequency values for the vector. + */ + public TokenOccurenceVector(List originalVector) { + this.originalVector = originalVector; + } + + /** + * Return a occurrence frequency value of the vector at the specified. + * @param index is the specified index. + * @return the occurrence frequency value or zero if the index is beyond the size of the vector. + */ + public double get(int index) { + if (index >= originalVector.size()) { + return 0.0; + } + return originalVector.get(index); + } + + /** + * The original size of the vector, without padding. + * @return the size. + */ + public int size() { + return originalVector.size(); + } +} \ No newline at end of file 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..734b1d081 --- /dev/null +++ b/languages/emf-metamodel/src/main/java/de/jplag/emf/normalization/TokenVectorGenerator.java @@ -0,0 +1,57 @@ +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.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 zero padded token occurrence vector, where each entry represents the number of tokens in the subtree. The + * order is determined by {@link ModelingElementTokenizer#allTokenTypes()}. + */ + public TokenOccurenceVector 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 new TokenOccurenceVector(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..5ea3adf11 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; /** @@ -40,10 +41,10 @@ public EcoreParser() { * @param files is the set of files. * @return the list of parsed tokens. */ - public List parse(Set files) throws ParsingException { + public List parse(Set files, boolean normalize) throws ParsingException { tokens = new ArrayList<>(); for (File file : files) { - parseModelFile(file); + parseModelFile(file, normalize); } return tokens; } @@ -52,20 +53,47 @@ public List parse(Set files) throws ParsingException { * Loads a metamodel from a file and parses it. * @param file is the metamodel file. */ - protected void parseModelFile(File file) throws ParsingException { + protected void parseModelFile(File file, boolean normalize) throws ParsingException { currentFile = file; Resource model = EMFUtil.loadModelResource(file); if (model == null) { throw new ParsingException(file, "failed to load model"); - } else { - treeView = new EmfaticModelView(file, model); - for (EObject root : model.getContents()) { - visitor = createMetamodelVisitor(); - visitor.visit(root); - } - tokens.add(Token.fileEnd(currentFile)); - treeView.writeToFile(Language.VIEW_FILE_SUFFIX); } + if (normalize) { + normalizeOrder(model); + } + treeView = createView(file, model); + visitor = createMetamodelVisitor(); + for (EObject root : model.getContents()) { + visitor.visit(root); + } + tokens.add(Token.fileEnd(currentFile)); + 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()); } /** @@ -81,7 +109,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..1d2b83c09 --- /dev/null +++ b/languages/emf-metamodel/src/main/java/de/jplag/emf/parser/MetamodelElementTokenizer.java @@ -0,0 +1,110 @@ +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; + } + return MetamodelTokenType.ATTRIBUTE; + } + + @Override + public MetamodelTokenType caseEClass(EClass eClass) { + if (eClass.isInterface()) { + return MetamodelTokenType.INTERFACE; + } + if (eClass.isAbstract()) { + return MetamodelTokenType.ABSTRACT_CLASS; + } + 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; + } + return MetamodelTokenType.CONTAINMENT_MULT; + } + if (eReference.getUpperBound() == 1) { + return MetamodelTokenType.REFERENCE; + } + 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/GenericEmfTreeView.java b/languages/emf-metamodel/src/main/java/de/jplag/emf/util/GenericEmfTreeView.java new file mode 100644 index 000000000..f68e08620 --- /dev/null +++ b/languages/emf-metamodel/src/main/java/de/jplag/emf/util/GenericEmfTreeView.java @@ -0,0 +1,153 @@ +package de.jplag.emf.util; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.StringJoiner; + +import org.eclipse.emf.ecore.ENamedElement; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.resource.Resource; + +import de.jplag.TokenTrace; +import de.jplag.emf.MetamodelToken; + +/** + * Very basic tree view representation of an EMF metamodel or model. + */ +public class GenericEmfTreeView extends AbstractModelView { + private final List lines; + private final Map objectToLine; + private final ModelingElementIdentifierManager identifierManager; + + /** + * Creates a tree view for a metamodel. + * @param file is the path to the metamodel. + */ + public GenericEmfTreeView(File file, Resource modelResource) { + super(file); + lines = new ArrayList<>(); + objectToLine = new HashMap<>(); + identifierManager = new ModelingElementIdentifierManager(); + 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. + */ + @Override + public MetamodelToken convertToMetadataEnrichedToken(MetamodelToken token) { + Optional optionalEObject = token.getEObject(); + if (optionalEObject.isPresent()) { + 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()); + } + + private final class TreeViewBuilder extends AbstractMetamodelVisitor { + private static final String IDENTIFIER_PREFIX = " #"; + private static final String VALUE_ASSIGNMENT = "="; + private static final String COLLECTION_PREFIX = "["; + private static final String COLLECTION_SUFFIX = "]"; + private static final String COLLECTION_DELIMITER = ", "; + private static final int ABBREVIATION_LIMIT = 20; + private static final String ABBREVIATION_SUFFIX = "..."; + private static final String TEXT_AFFIX = "\""; + private static final String IDENTIFIER_REGEX = "name|identifier"; + private static final String INDENTATION = " "; + + @Override + protected void visitEObject(EObject eObject) { + String prefix = INDENTATION.repeat(getCurrentTreeDepth()); + StringBuilder line = new StringBuilder(prefix); + + line.append(eObject.eClass().getName()); // Build element type + line.append(IDENTIFIER_PREFIX); + line.append(identifierManager.getIdentifier(eObject)); + visitStructuralFeatures(eObject, line); // Build element features + + lines.add(line.toString()); + viewBuilder.append(line + System.lineSeparator()); + // line and column values are one-indexed + TokenTrace trace = new TokenTrace(lines.size(), prefix.length() + 1, line.toString().trim().length()); + objectToLine.put(eObject, trace); + } + + private void visitStructuralFeatures(EObject eObject, StringBuilder line) { + List structuralFeatures = eObject.eClass().getEAllStructuralFeatures(); + if (!structuralFeatures.isEmpty()) { + line.append(": "); + StringJoiner joiner = new StringJoiner(COLLECTION_DELIMITER); + for (EStructuralFeature feature : structuralFeatures) { + Object value = eObject.eGet(feature); + String name = featureValueToString(value); + if (name != null) { + joiner.add(feature.getName() + VALUE_ASSIGNMENT + name); + } + } + line.append(joiner.toString()); + + } + } + + private String featureValueToString(Object value) { + String name = null; + if (value != null) { + if (value instanceof EObject featureValue) { + List valueIdentifiers = deriveNameOrIdentifers(featureValue); + + if (!valueIdentifiers.isEmpty()) { + name = TEXT_AFFIX + valueIdentifiers.get(0) + TEXT_AFFIX; + } else { + name = featureValue.eClass().getName() + IDENTIFIER_PREFIX + identifierManager.getIdentifier(featureValue); + } + } else if (value instanceof Collection multipleValues) { + name = valueListToString(multipleValues); + } else { + name = value.toString(); + name = (name.length() > ABBREVIATION_LIMIT) ? name.substring(0, ABBREVIATION_LIMIT) + ABBREVIATION_SUFFIX : name; + name = TEXT_AFFIX + name + TEXT_AFFIX; + } + } + return name; + } + + private String valueListToString(Collection multipleValues) { + String name = null; + if (!multipleValues.isEmpty()) { + name = COLLECTION_PREFIX; + StringJoiner joiner = new StringJoiner(COLLECTION_DELIMITER); + for (Object innerValue : multipleValues) { + joiner.add(featureValueToString(innerValue)); + } + name += joiner.toString() + COLLECTION_SUFFIX; + } + return name; + } + + private static List deriveNameOrIdentifers(EObject eObject) { + List names = new ArrayList<>(); + if (eObject instanceof ENamedElement element) { + names.add(element.getName()); + } else { + for (EStructuralFeature feature : eObject.eClass().getEAllStructuralFeatures()) { + if (feature.getName().toLowerCase().matches(IDENTIFIER_REGEX) && eObject.eGet(feature) != null) { + names.add(eObject.eGet(feature).toString()); + } + } + } + return names; + } + } + +} 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 deleted file mode 100644 index 36a736e01..000000000 --- a/languages/emf-metamodel/src/main/java/de/jplag/emf/util/MetamodelTreeView.java +++ /dev/null @@ -1,75 +0,0 @@ -package de.jplag.emf.util; - -import java.io.File; -import java.util.Optional; - -import org.eclipse.emf.ecore.ENamedElement; -import org.eclipse.emf.ecore.EObject; - -import de.jplag.Token; -import de.jplag.emf.MetamodelToken; - -/** - * Simplistic tree view representation of an EMF metamodel. - * @author Timur Saglam - */ -public class MetamodelTreeView extends AbstractModelView { - - private int lineIndex; - private int columnIndex; - - private static final String INDENTATION = " "; - - /** - * Creates a tree view for a metamodel. - * @param file is the path to the metamodel. - */ - public MetamodelTreeView(File file) { - super(file); - } - - /** - * 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; - Optional optionalEObject = token.getEObject(); - if (optionalEObject.isPresent()) { - EObject eObject = optionalEObject.get(); - if (prefix.isEmpty() && treeDepth > 0) { - lineIndex++; - columnIndex = 0; - viewBuilder.append(System.lineSeparator()); - } - - String tokenText = token.getType().getDescription(); - if (eObject instanceof ENamedElement element) { - tokenText = element.getName() + " : " + tokenText; - } - length = tokenText.length(); - - 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(); - } - - line = lineIndex + 1; - column = columnIndex + 1; - - columnIndex += tokenText.length(); - } - return new MetamodelToken(token.getType(), token.getFile(), line, column, length, token.getEObject()); - } - -} diff --git a/languages/emf-metamodel/src/main/java/de/jplag/emf/util/ModelingElementIdentifierManager.java b/languages/emf-metamodel/src/main/java/de/jplag/emf/util/ModelingElementIdentifierManager.java new file mode 100644 index 000000000..895087dd6 --- /dev/null +++ b/languages/emf-metamodel/src/main/java/de/jplag/emf/util/ModelingElementIdentifierManager.java @@ -0,0 +1,42 @@ +package de.jplag.emf.util; + +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EObject; + +/** + * This class provides type-unique identifiers for EObjects. + */ +public class ModelingElementIdentifierManager { + + private final Map> elementToIdentifer; + + /** + * Creates the identifier manager. Identifiers are only unique if managed by the same instance. + */ + public ModelingElementIdentifierManager() { + elementToIdentifer = new HashMap<>(); + } + + /** + * Returns the type-unique identifier for any EMF modeling element. + * @param element is the modeling element for which the identifier is requested. + * @return the identifier, that is unique for all elements of the same EClass. + */ + public int getIdentifier(EObject element) { + Set elements = elementToIdentifer.computeIfAbsent(element.eClass(), key -> new LinkedHashSet<>()); + int index = 0; + for (EObject containedElement : elements) { + if (containedElement.equals(element)) { + return index; + } + ++index; + } + elements.add(element); + return index; + } +} 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..c2559f7c8 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 @@ -28,13 +28,13 @@ class MinimalMetamodelTest extends AbstractEmfTest { @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 result = language.parse(new HashSet<>(testFiles), true); - 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/GenericEmfTreeViewTest.java b/languages/emf-metamodel/src/test/java/de/jplag/emf/util/GenericEmfTreeViewTest.java new file mode 100644 index 000000000..bef41d57b --- /dev/null +++ b/languages/emf-metamodel/src/test/java/de/jplag/emf/util/GenericEmfTreeViewTest.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 GenericEmfTreeViewTest 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 generic EMF 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: + GenericEmfTreeView view = new GenericEmfTreeView(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..05c24f48e --- /dev/null +++ b/languages/emf-metamodel/src/test/resources/de/jplag/treeview/bookStore.ecore.treeview @@ -0,0 +1,13 @@ +EPackage #0: name="BookStorePackage", nsURI="http:///com.ibm.dyna...", nsPrefix="bookStore", eFactoryInstance=EFactory #0, eClassifiers=["BookStore", "Book"] + EClass #0: name="BookStore", ePackage="BookStorePackage", abstract="false", interface="false", eAllAttributes=["owner", "location"], eAllReferences=["books"], eReferences=["books"], eAttributes=["owner", "location"], eAllContainments=["books"], eAllStructuralFeatures=["owner", "location", "books"], eStructuralFeatures=["owner", "location", "books"] + EAttribute #0: name="owner", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="EString", eGenericType=EGenericType #0, changeable="true", volatile="false", transient="false", unsettable="false", derived="false", eContainingClass="BookStore", iD="false", eAttributeType="EString" + EGenericType #0: eRawType="EString", eClassifier="EString" + EAttribute #1: name="location", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="EString", eGenericType=EGenericType #1, changeable="true", volatile="false", transient="false", unsettable="false", derived="false", eContainingClass="BookStore", iD="false", eAttributeType="EString" + EGenericType #1: eRawType="EString", eClassifier="EString" + EReference #0: name="books", ordered="true", unique="true", lowerBound="0", upperBound="-1", many="true", required="false", eType="Book", eGenericType=EGenericType #2, changeable="true", volatile="false", transient="false", unsettable="false", derived="false", eContainingClass="BookStore", containment="true", container="false", resolveProxies="true", eReferenceType="Book" + EGenericType #2: eRawType="Book", eClassifier="Book" + EClass #1: name="Book", ePackage="BookStorePackage", abstract="false", interface="false", eAllAttributes=["name", "isbn"], eAttributes=["name", "isbn"], eAllStructuralFeatures=["name", "isbn"], eIDAttribute="isbn", eStructuralFeatures=["name", "isbn"] + EAttribute #2: name="name", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="EString", eGenericType=EGenericType #3, changeable="true", volatile="false", transient="false", unsettable="false", derived="false", eContainingClass="Book", iD="false", eAttributeType="EString" + EGenericType #3: eRawType="EString", eClassifier="EString" + EAttribute #3: name="isbn", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="EInt", eGenericType=EGenericType #4, changeable="true", volatile="false", transient="false", defaultValue="0", unsettable="false", derived="false", eContainingClass="Book", iD="true", eAttributeType="EInt" + EGenericType #4: eRawType="EInt", eClassifier="EInt" 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..d70740d4f --- /dev/null +++ b/languages/emf-metamodel/src/test/resources/de/jplag/treeview/bookStoreExtended.ecore.treeview @@ -0,0 +1,35 @@ +EPackage #0: name="BookStorePackage", nsURI="http:///com.ibm.dyna...", nsPrefix="bookStore", eFactoryInstance=EFactory #0, eSubpackages=["store", "person"] + EPackage #1: name="store", nsURI="http:///com.ibm.dyna...", nsPrefix="store", eFactoryInstance=EFactory #1, eClassifiers=["BookStore", "Book", "Genre"], eSuperPackage="BookStorePackage" + EClass #0: name="BookStore", ePackage="store", abstract="false", interface="false", eAllAttributes=["name", "location"], eAllReferences=["owner", "books"], eReferences=["owner", "books"], eAttributes=["name", "location"], eAllContainments=["books"], eAllStructuralFeatures=["owner", "name", "location", "books"], eStructuralFeatures=["owner", "name", "location", "books"] + EReference #0: name="owner", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="Person", eGenericType=EGenericType #0, changeable="true", volatile="false", transient="false", unsettable="false", derived="false", eContainingClass="BookStore", containment="false", container="false", resolveProxies="true", eReferenceType="Person" + EGenericType #0: eRawType="Person", eClassifier="Person" + EAttribute #0: name="name", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="EString", eGenericType=EGenericType #1, changeable="true", volatile="false", transient="false", unsettable="false", derived="false", eContainingClass="BookStore", iD="false", eAttributeType="EString" + EGenericType #1: eRawType="EString", eClassifier="EString" + EAttribute #1: name="location", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="EString", eGenericType=EGenericType #2, changeable="true", volatile="false", transient="false", unsettable="false", derived="false", eContainingClass="BookStore", iD="false", eAttributeType="EString" + EGenericType #2: eRawType="EString", eClassifier="EString" + EReference #1: name="books", ordered="true", unique="true", lowerBound="0", upperBound="-1", many="true", required="false", eType="Book", eGenericType=EGenericType #3, changeable="true", volatile="false", transient="false", unsettable="false", derived="false", eContainingClass="BookStore", containment="true", container="false", resolveProxies="true", eReferenceType="Book" + EGenericType #3: eRawType="Book", eClassifier="Book" + EClass #1: name="Book", ePackage="store", abstract="false", interface="false", eAllAttributes=["name", "isbn", "genre"], eAllReferences=["author"], eReferences=["author"], eAttributes=["name", "isbn", "genre"], eAllStructuralFeatures=["name", "isbn", "author", "genre"], eIDAttribute="isbn", eStructuralFeatures=["name", "isbn", "author", "genre"] + EAttribute #2: name="name", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="EString", eGenericType=EGenericType #4, changeable="true", volatile="false", transient="false", unsettable="false", derived="false", eContainingClass="Book", iD="false", eAttributeType="EString" + EGenericType #4: eRawType="EString", eClassifier="EString" + EAttribute #3: name="isbn", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="EInt", eGenericType=EGenericType #5, changeable="true", volatile="false", transient="false", defaultValue="0", unsettable="false", derived="false", eContainingClass="Book", iD="true", eAttributeType="EInt" + EGenericType #5: eRawType="EInt", eClassifier="EInt" + EReference #2: name="author", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="Author", eGenericType=EGenericType #6, changeable="true", volatile="false", transient="false", unsettable="false", derived="false", eContainingClass="Book", containment="false", container="false", resolveProxies="true", eReferenceType="Author" + EGenericType #6: eRawType="Author", eClassifier="Author" + EAttribute #4: name="genre", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="Genre", eGenericType=EGenericType #7, changeable="true", volatile="false", transient="false", defaultValue="NOVEL", unsettable="false", derived="false", eContainingClass="Book", iD="false", eAttributeType="Genre" + EGenericType #7: eRawType="Genre", eClassifier="Genre" + EEnum #0: name="Genre", defaultValue="NOVEL", ePackage="store", serializable="true", eLiterals=["NOVEL", "COOKBOOK", "BIOGRAPHY", "TEXTBOOK"] + EEnumLiteral #0: name="NOVEL", value="0", instance="NOVEL", literal="NOVEL", eEnum="Genre" + EEnumLiteral #1: name="COOKBOOK", value="1", instance="COOKBOOK", literal="COOKBOOK", eEnum="Genre" + EEnumLiteral #2: name="BIOGRAPHY", value="3", instance="BIOGRAPHY", literal="BIOGRAPHY", eEnum="Genre" + EEnumLiteral #3: name="TEXTBOOK", value="4", instance="TEXTBOOK", literal="TEXTBOOK", eEnum="Genre" + EPackage #2: name="person", nsURI="http:///com.ibm.dyna...", nsPrefix="person", eFactoryInstance=EFactory #2, eClassifiers=["Author", "Person"], eSuperPackage="BookStorePackage" + EClass #2: name="Author", ePackage="person", abstract="false", interface="false", eSuperTypes=["Person"], eAllAttributes=["firstName", "lastName", "isStageName"], eAttributes=["isStageName"], eAllStructuralFeatures=["firstName", "lastName", "isStageName"], eAllSuperTypes=["Person"], eStructuralFeatures=["isStageName"], eGenericSuperTypes=[EGenericType #8], eAllGenericSuperTypes=[EGenericType #8] + EAttribute #5: name="isStageName", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="EBoolean", eGenericType=EGenericType #9, changeable="true", volatile="false", transient="false", defaultValue="false", unsettable="false", derived="false", eContainingClass="Author", iD="false", eAttributeType="EBoolean" + EGenericType #9: eRawType="EBoolean", eClassifier="EBoolean" + EGenericType #8: eRawType="Person", eClassifier="Person" + EClass #3: name="Person", ePackage="person", abstract="false", interface="false", eAllAttributes=["firstName", "lastName"], eAttributes=["firstName", "lastName"], eAllStructuralFeatures=["firstName", "lastName"], eStructuralFeatures=["firstName", "lastName"] + EAttribute #6: name="firstName", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="EString", eGenericType=EGenericType #10, changeable="true", volatile="false", transient="false", unsettable="false", derived="false", eContainingClass="Person", iD="false", eAttributeType="EString" + EGenericType #10: eRawType="EString", eClassifier="EString" + EAttribute #7: name="lastName", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="EString", eGenericType=EGenericType #11, changeable="true", volatile="false", transient="false", unsettable="false", derived="false", eContainingClass="Person", iD="false", eAttributeType="EString" + EGenericType #11: eRawType="EString", eClassifier="EString" 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..ee121f2ea --- /dev/null +++ b/languages/emf-metamodel/src/test/resources/de/jplag/treeview/bookStoreExtendedRefactor.ecore.treeview @@ -0,0 +1,29 @@ +EPackage #0: name="BookStorePackage", nsURI="http:///com.ibm.dyna...", nsPrefix="bookStore", eFactoryInstance=EFactory #0, eSubpackages=["store"] + EPackage #1: name="store", nsURI="http:///com.ibm.dyna...", nsPrefix="store", eFactoryInstance=EFactory #1, eClassifiers=["Store", "BookStore", "Book", "Person"], eSuperPackage="BookStorePackage" + EClass #0: name="Store", ePackage="store", abstract="false", interface="false", eAllAttributes=["name", "location"], eAllReferences=["owner"], eReferences=["owner"], eAttributes=["name", "location"], eAllStructuralFeatures=["owner", "name", "location"], eStructuralFeatures=["owner", "name", "location"] + EReference #0: name="owner", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="Person", eGenericType=EGenericType #0, changeable="true", volatile="false", transient="false", unsettable="false", derived="false", eContainingClass="Store", containment="false", container="false", resolveProxies="true", eReferenceType="Person" + EGenericType #0: eRawType="Person", eClassifier="Person" + EAttribute #0: name="name", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="EString", eGenericType=EGenericType #1, changeable="true", volatile="false", transient="false", unsettable="false", derived="false", eContainingClass="Store", iD="false", eAttributeType="EString" + EGenericType #1: eRawType="EString", eClassifier="EString" + EAttribute #1: name="location", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="EString", eGenericType=EGenericType #2, changeable="true", volatile="false", transient="false", unsettable="false", derived="false", eContainingClass="Store", iD="false", eAttributeType="EString" + EGenericType #2: eRawType="EString", eClassifier="EString" + EClass #1: name="BookStore", ePackage="store", abstract="false", interface="false", eSuperTypes=["Store"], eAllAttributes=["name", "location"], eAllReferences=["owner", "books"], eReferences=["books"], eAllContainments=["books"], eAllStructuralFeatures=["owner", "name", "location", "books"], eAllSuperTypes=["Store"], eStructuralFeatures=["books"], eGenericSuperTypes=[EGenericType #3], eAllGenericSuperTypes=[EGenericType #3] + EReference #1: name="books", ordered="true", unique="true", lowerBound="0", upperBound="-1", many="true", required="false", eType="Book", eGenericType=EGenericType #4, changeable="true", volatile="false", transient="false", unsettable="false", derived="false", eContainingClass="BookStore", containment="true", container="false", resolveProxies="true", eReferenceType="Book" + EGenericType #4: eRawType="Book", eClassifier="Book" + EGenericType #3: eRawType="Store", eClassifier="Store" + EClass #2: name="Book", ePackage="store", abstract="false", interface="false", eAllAttributes=["title", "isbn", "category"], eAllReferences=["author"], eReferences=["author"], eAttributes=["title", "isbn", "category"], eAllStructuralFeatures=["title", "isbn", "author", "category"], eIDAttribute="isbn", eStructuralFeatures=["title", "isbn", "author", "category"] + EAttribute #2: name="title", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="EString", eGenericType=EGenericType #5, changeable="true", volatile="false", transient="false", unsettable="false", derived="false", eContainingClass="Book", iD="false", eAttributeType="EString" + EGenericType #5: eRawType="EString", eClassifier="EString" + EAttribute #3: name="isbn", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="EInt", eGenericType=EGenericType #6, changeable="true", volatile="false", transient="false", defaultValue="0", unsettable="false", derived="false", eContainingClass="Book", iD="true", eAttributeType="EInt" + EGenericType #6: eRawType="EInt", eClassifier="EInt" + EReference #2: name="author", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="Person", eGenericType=EGenericType #7, changeable="true", volatile="false", transient="false", unsettable="false", derived="false", eContainingClass="Book", containment="false", container="false", resolveProxies="true", eReferenceType="Person" + EGenericType #7: eRawType="Person", eClassifier="Person" + EAttribute #4: name="category", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="EString", eGenericType=EGenericType #8, changeable="true", volatile="false", transient="false", unsettable="false", derived="false", eContainingClass="Book", iD="false", eAttributeType="EString" + EGenericType #8: eRawType="EString", eClassifier="EString" + EClass #3: name="Person", ePackage="store", abstract="false", interface="false", eAllAttributes=["firstName", "lastName", "isStageName"], eAttributes=["firstName", "lastName", "isStageName"], eAllStructuralFeatures=["firstName", "lastName", "isStageName"], eStructuralFeatures=["firstName", "lastName", "isStageName"] + EAttribute #5: name="firstName", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="EString", eGenericType=EGenericType #9, changeable="true", volatile="false", transient="false", unsettable="false", derived="false", eContainingClass="Person", iD="false", eAttributeType="EString" + EGenericType #9: eRawType="EString", eClassifier="EString" + EAttribute #6: name="lastName", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="EString", eGenericType=EGenericType #10, changeable="true", volatile="false", transient="false", unsettable="false", derived="false", eContainingClass="Person", iD="false", eAttributeType="EString" + EGenericType #10: eRawType="EString", eClassifier="EString" + EAttribute #7: name="isStageName", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="EBoolean", eGenericType=EGenericType #11, changeable="true", volatile="false", transient="false", defaultValue="false", unsettable="false", derived="false", eContainingClass="Person", iD="false", eAttributeType="EBoolean" + EGenericType #11: eRawType="EBoolean", eClassifier="EBoolean" 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..43ab1ee1a --- /dev/null +++ b/languages/emf-metamodel/src/test/resources/de/jplag/treeview/bookStoreRenamed.ecore.treeview @@ -0,0 +1,13 @@ +EPackage #0: name="BookStorePackage", nsURI="http:///com.ibm.dyna...", nsPrefix="bookStore", eFactoryInstance=EFactory #0, eClassifiers=["Store", "Item"] + EClass #0: name="Store", ePackage="BookStorePackage", abstract="false", interface="false", eAllAttributes=["nameOfOwner", "city"], eAllReferences=["soldItems"], eReferences=["soldItems"], eAttributes=["nameOfOwner", "city"], eAllContainments=["soldItems"], eAllStructuralFeatures=["nameOfOwner", "city", "soldItems"], eStructuralFeatures=["nameOfOwner", "city", "soldItems"] + EAttribute #0: name="nameOfOwner", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="EString", eGenericType=EGenericType #0, changeable="true", volatile="false", transient="false", unsettable="false", derived="false", eContainingClass="Store", iD="false", eAttributeType="EString" + EGenericType #0: eRawType="EString", eClassifier="EString" + EAttribute #1: name="city", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="EString", eGenericType=EGenericType #1, changeable="true", volatile="false", transient="false", unsettable="false", derived="false", eContainingClass="Store", iD="false", eAttributeType="EString" + EGenericType #1: eRawType="EString", eClassifier="EString" + EReference #0: name="soldItems", ordered="true", unique="true", lowerBound="0", upperBound="-1", many="true", required="false", eType="Item", eGenericType=EGenericType #2, changeable="true", volatile="false", transient="false", unsettable="false", derived="false", eContainingClass="Store", containment="true", container="false", resolveProxies="true", eReferenceType="Item" + EGenericType #2: eRawType="Item", eClassifier="Item" + EClass #1: name="Item", ePackage="BookStorePackage", abstract="false", interface="false", eAllAttributes=["title", "identifier"], eAttributes=["title", "identifier"], eAllStructuralFeatures=["title", "identifier"], eIDAttribute="identifier", eStructuralFeatures=["title", "identifier"] + EAttribute #2: name="title", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="EString", eGenericType=EGenericType #3, changeable="true", volatile="false", transient="false", unsettable="false", derived="false", eContainingClass="Item", iD="false", eAttributeType="EString" + EGenericType #3: eRawType="EString", eClassifier="EString" + EAttribute #3: name="identifier", ordered="true", unique="true", lowerBound="0", upperBound="1", many="false", required="false", eType="EInt", eGenericType=EGenericType #4, changeable="true", volatile="false", transient="false", defaultValue="0", unsettable="false", derived="false", eContainingClass="Item", iD="true", eAttributeType="EInt" + EGenericType #4: eRawType="EInt", eClassifier="EInt" diff --git a/languages/emf-model/README.md b/languages/emf-model/README.md new file mode 100644 index 000000000..0f63945ad --- /dev/null +++ b/languages/emf-model/README.md @@ -0,0 +1,24 @@ +# Dynamic EMF model language module +The dynamic EMF model language module allows the use of JPlag with model submissions. +It is based on the EMF API. + +### EMF specification compatibility +This module is based on the EMF dependencies available on maven central. These might not be the newest versions of EMF. For details, the [JPlag aggregator pom](https://github.com/jplag/JPlag/blob/263e85e544152cc8b0caa3399127debb7a458746/pom.xml#L84-L86). + +### Token Extraction +For the token extraction, we visit the containment tree of the model and extract tokens for all model elements based on their concrete metaclass. In this module, we thus extract tokens based on a dynamic token set. This works well for structural models with tree-like structures. It is less effective for models where the containment structure is not semantically relevant (e.g. state charts). These kinds of models require a dedicated language module. + +### Usage +The input for this is an EMF metamodel and a set of corresponding instances. +To ensure only the intended files are parsed, you can use `-p` to specify allowed file types: `-p ecore,xmi,mysuffix`. +To use this module, add the `-l emf-model` 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). + +### Report Viewer +In the report viewer, a simple textual syntax is used to generate a tree-based model view. +To provide a custom visualization of a specific metamodel, a custom language module is required. + +### Literature +* [*"Token-based Plagiarism Detection for Metamodels" (MODELS-C'22)*](https://dl.acm.org/doi/10.1145/3550356.3556508). +* Its [Kudos Summary](https://www.growkudos.com/publications/10.1145%25252F3550356.3556508/reader). +* [*"Token-based Plagiarism Detection for Metamodels" (MODELS-C'22)*] +* *"Automated Detection of AI-Obfuscated Plagiarism in Modeling Assignments" (ICSE-SEET'24)* \ No newline at end of file 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..e64036bfa --- /dev/null +++ b/languages/emf-model/src/main/java/de/jplag/emf/model/EmfModelLanguage.java @@ -0,0 +1,57 @@ +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) { + return sub.stream().sorted(Comparator.comparing(file -> file.getName().endsWith(FILE_ENDING) ? 0 : 1)).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..e2d4ac3ed --- /dev/null +++ b/languages/emf-model/src/main/java/de/jplag/emf/model/parser/DynamicModelParser.java @@ -0,0 +1,78 @@ +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.GenericEmfTreeView; + +/** + * 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, boolean normalize) 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, normalize); + } + } + + @Override + protected String getCorrespondingViewFileSuffix() { + return EmfModelLanguage.VIEW_FILE_SUFFIX; + } + + @Override + protected AbstractModelView createView(File file, Resource modelResource) { + return new GenericEmfTreeView(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); + } + 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..2ff7001ad --- /dev/null +++ b/languages/emf-model/src/test/java/de/jplag/emf/model/MinimalModelInstanceTest.java @@ -0,0 +1,66 @@ +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.LinkedHashSet; +import java.util.List; +import java.util.Optional; + +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.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 LinkedHashSet<>(language.customizeSubmissionOrder(baseFiles)); + try { + List tokens = language.parse(sortedFiles, true); + assertNotEquals(0, tokens.size()); + logger.debug(TokenPrinter.printTokens(tokens, baseDirectory, Optional.of(EmfModelLanguage.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 84% 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..3dbd09ec4 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(); } @@ -43,7 +43,7 @@ public int minimumTokenMatch() { } @Override - public List parse(Set files) throws ParsingException { + public List parse(Set files, boolean normalize) throws ParsingException { return parserAdapter.parse(files); } } 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/main/java/de/jplag/golang/JPlagGoListener.java b/languages/golang/src/main/java/de/jplag/golang/JPlagGoListener.java index 504e2337e..8774fb81d 100644 --- a/languages/golang/src/main/java/de/jplag/golang/JPlagGoListener.java +++ b/languages/golang/src/main/java/de/jplag/golang/JPlagGoListener.java @@ -1,8 +1,79 @@ package de.jplag.golang; -import static de.jplag.golang.GoTokenType.*; - -import java.util.*; +import static de.jplag.golang.GoTokenType.ARGUMENT; +import static de.jplag.golang.GoTokenType.ARRAY_BODY_BEGIN; +import static de.jplag.golang.GoTokenType.ARRAY_BODY_END; +import static de.jplag.golang.GoTokenType.ARRAY_CONSTRUCTOR; +import static de.jplag.golang.GoTokenType.ARRAY_ELEMENT; +import static de.jplag.golang.GoTokenType.ASSIGNMENT; +import static de.jplag.golang.GoTokenType.BREAK; +import static de.jplag.golang.GoTokenType.CASE_BLOCK_BEGIN; +import static de.jplag.golang.GoTokenType.CASE_BLOCK_END; +import static de.jplag.golang.GoTokenType.CONTINUE; +import static de.jplag.golang.GoTokenType.DEFER; +import static de.jplag.golang.GoTokenType.ELSE_BLOCK_BEGIN; +import static de.jplag.golang.GoTokenType.ELSE_BLOCK_END; +import static de.jplag.golang.GoTokenType.FALLTHROUGH; +import static de.jplag.golang.GoTokenType.FOR_BLOCK_BEGIN; +import static de.jplag.golang.GoTokenType.FOR_BLOCK_END; +import static de.jplag.golang.GoTokenType.FOR_STATEMENT; +import static de.jplag.golang.GoTokenType.FUNCTION_BODY_BEGIN; +import static de.jplag.golang.GoTokenType.FUNCTION_BODY_END; +import static de.jplag.golang.GoTokenType.FUNCTION_DECLARATION; +import static de.jplag.golang.GoTokenType.FUNCTION_LITERAL; +import static de.jplag.golang.GoTokenType.FUNCTION_PARAMETER; +import static de.jplag.golang.GoTokenType.GO; +import static de.jplag.golang.GoTokenType.GOTO; +import static de.jplag.golang.GoTokenType.IF_BLOCK_BEGIN; +import static de.jplag.golang.GoTokenType.IF_BLOCK_END; +import static de.jplag.golang.GoTokenType.IF_STATEMENT; +import static de.jplag.golang.GoTokenType.IMPORT_CLAUSE; +import static de.jplag.golang.GoTokenType.IMPORT_CLAUSE_BEGIN; +import static de.jplag.golang.GoTokenType.IMPORT_CLAUSE_END; +import static de.jplag.golang.GoTokenType.IMPORT_DECLARATION; +import static de.jplag.golang.GoTokenType.INTERFACE_BLOCK_BEGIN; +import static de.jplag.golang.GoTokenType.INTERFACE_BLOCK_END; +import static de.jplag.golang.GoTokenType.INTERFACE_DECLARATION; +import static de.jplag.golang.GoTokenType.INTERFACE_METHOD; +import static de.jplag.golang.GoTokenType.INVOCATION; +import static de.jplag.golang.GoTokenType.MAP_BODY_BEGIN; +import static de.jplag.golang.GoTokenType.MAP_BODY_END; +import static de.jplag.golang.GoTokenType.MAP_CONSTRUCTOR; +import static de.jplag.golang.GoTokenType.MAP_ELEMENT; +import static de.jplag.golang.GoTokenType.MEMBER_DECLARATION; +import static de.jplag.golang.GoTokenType.NAMED_TYPE_BODY_BEGIN; +import static de.jplag.golang.GoTokenType.NAMED_TYPE_BODY_END; +import static de.jplag.golang.GoTokenType.NAMED_TYPE_CONSTRUCTOR; +import static de.jplag.golang.GoTokenType.NAMED_TYPE_ELEMENT; +import static de.jplag.golang.GoTokenType.PACKAGE; +import static de.jplag.golang.GoTokenType.RECEIVER; +import static de.jplag.golang.GoTokenType.RECEIVE_STATEMENT; +import static de.jplag.golang.GoTokenType.RETURN; +import static de.jplag.golang.GoTokenType.SELECT_BLOCK_BEGIN; +import static de.jplag.golang.GoTokenType.SELECT_BLOCK_END; +import static de.jplag.golang.GoTokenType.SELECT_STATEMENT; +import static de.jplag.golang.GoTokenType.SEND_STATEMENT; +import static de.jplag.golang.GoTokenType.SLICE_BODY_BEGIN; +import static de.jplag.golang.GoTokenType.SLICE_BODY_END; +import static de.jplag.golang.GoTokenType.SLICE_CONSTRUCTOR; +import static de.jplag.golang.GoTokenType.SLICE_ELEMENT; +import static de.jplag.golang.GoTokenType.STATEMENT_BLOCK_BEGIN; +import static de.jplag.golang.GoTokenType.STATEMENT_BLOCK_END; +import static de.jplag.golang.GoTokenType.STRUCT_BODY_BEGIN; +import static de.jplag.golang.GoTokenType.STRUCT_BODY_END; +import static de.jplag.golang.GoTokenType.STRUCT_DECLARATION; +import static de.jplag.golang.GoTokenType.SWITCH_BLOCK_BEGIN; +import static de.jplag.golang.GoTokenType.SWITCH_BLOCK_END; +import static de.jplag.golang.GoTokenType.SWITCH_CASE; +import static de.jplag.golang.GoTokenType.SWITCH_STATEMENT; +import static de.jplag.golang.GoTokenType.TYPE_ASSERTION; +import static de.jplag.golang.GoTokenType.TYPE_CONSTRAINT; +import static de.jplag.golang.GoTokenType.VARIABLE_DECLARATION; + +import java.util.Arrays; +import java.util.Deque; +import java.util.LinkedList; +import java.util.Optional; import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.tree.TerminalNode; 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/FixedSourcePositions.java b/languages/java/src/main/java/de/jplag/java/FixedSourcePositions.java new file mode 100644 index 000000000..7d031aa7c --- /dev/null +++ b/languages/java/src/main/java/de/jplag/java/FixedSourcePositions.java @@ -0,0 +1,30 @@ +package de.jplag.java; + +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.Tree; +import com.sun.source.util.SourcePositions; + +/** + * Fixes the source positions, so that the end position is always at least the same as the start position. + */ +public class FixedSourcePositions implements SourcePositions { + private final SourcePositions base; + + /** + * New instance + * @param base The source positions to use as the base + */ + public FixedSourcePositions(SourcePositions base) { + this.base = base; + } + + @Override + public long getStartPosition(CompilationUnitTree compilationUnitTree, Tree tree) { + return this.base.getStartPosition(compilationUnitTree, tree); + } + + @Override + public long getEndPosition(CompilationUnitTree compilationUnitTree, Tree tree) { + return Math.max(this.getStartPosition(compilationUnitTree, tree), this.base.getEndPosition(compilationUnitTree, tree)); + } +} 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 62% 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..4db88ef01 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,13 @@ * 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"; + public static final int JAVA_VERSION = 21; private final Parser parser; - public Language() { + public JavaLanguage() { parser = new Parser(); } @@ -43,7 +44,22 @@ public int minimumTokenMatch() { } @Override - public List parse(Set files) throws ParsingException { + public List parse(Set files, boolean normalize) throws ParsingException { return this.parser.parse(files); } + + @Override + public boolean tokensHaveSemantics() { + return true; + } + + @Override + public boolean supportsNormalization() { + return true; + } + + @Override + public String toString() { + return this.getIdentifier(); + } } 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..f1c5c2dc9 100644 --- a/languages/java/src/main/java/de/jplag/java/JavacAdapter.java +++ b/languages/java/src/main/java/de/jplag/java/JavacAdapter.java @@ -2,11 +2,10 @@ 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; -import java.util.Locale; import java.util.Set; import javax.tools.DiagnosticCollector; @@ -20,6 +19,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,26 +35,27 @@ 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 // https://stackoverflow.com/questions/72737445/system-java-compiler-behaves-different-depending-on-dependencies-defined-in-mave - final CompilationTask task = javac.getTask(null, fileManager, listener, List.of("-proc:none"), null, javaFiles); + final CompilationTask task = javac.getTask(null, fileManager, listener, + List.of("-proc:none", "--enable-preview", "--release=" + JavaLanguage.JAVA_VERSION), null, javaFiles); final Trees trees = Trees.instance(task); - final SourcePositions positions = trees.getSourcePositions(); + final SourcePositions positions = new FixedSourcePositions(trees.getSourcePositions()); for (final CompilationUnitTree ast : executeCompilationTask(task, parser.logger)) { File file = new File(ast.getSourceFile().toUri()); final LineMap map = ast.getLineMap(); 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); } - parsingExceptions.addAll(processErrors(parser.logger, listener)); + parsingExceptions.addAll(processErrors(listener)); if (!parsingExceptions.isEmpty()) { throw ParsingException.wrappingExceptions(parsingExceptions); } @@ -70,15 +71,13 @@ private Iterable executeCompilationTask(final Com return abstractSyntaxTrees; } - private List processErrors(Logger logger, DiagnosticCollector listener) { + private List processErrors(DiagnosticCollector listener) { return listener.getDiagnostics().stream().filter(it -> it.getKind() == javax.tools.Diagnostic.Kind.ERROR).map(diagnosticItem -> { File file = null; - if (diagnosticItem.getSource() instanceof JavaFileObject) { - JavaFileObject fileObject = (JavaFileObject) diagnosticItem.getSource(); + if (diagnosticItem.getSource() instanceof JavaFileObject fileObject) { file = new File(fileObject.toUri()); } - logger.error("{}", diagnosticItem); - return new ParsingException(file, diagnosticItem.getMessage(Locale.getDefault())); + return new ParsingException(file, diagnosticItem.toString()); }).toList(); } 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..28bd5838a 100644 --- a/languages/java/src/main/java/de/jplag/java/TokenGeneratingTreeScanner.java +++ b/languages/java/src/main/java/de/jplag/java/TokenGeneratingTreeScanner.java @@ -1,15 +1,19 @@ package de.jplag.java; import java.io.File; -import java.util.ArrayList; -import java.util.List; 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; @@ -21,12 +25,13 @@ import com.sun.source.tree.DefaultCaseLabelTree; import com.sun.source.tree.DoWhileLoopTree; import com.sun.source.tree.EnhancedForLoopTree; -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 +55,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 static String ANONYMOUS_VARIABLE_NAME = ""; + 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 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,10 +79,12 @@ 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); } /** @@ -77,8 +93,8 @@ public List getParsingExceptions() { * @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 +103,468 @@ 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()); + + this.scan(node.getLabels(), null); + if (node.getGuard() != null) { + addToken(JavaTokenType.J_IF_BEGIN, positions.getStartPosition(ast, node.getGuard()), 0, CodeSemantics.createControl()); + } + this.scan(node.getGuard(), null); + if (node.getCaseKind() == CaseTree.CaseKind.RULE) { + this.scan(node.getBody(), null); + } else { + this.scan(node.getStatements(), null); + } + + if (node.getGuard() != null) { + addToken(JavaTokenType.J_IF_END, positions.getEndPosition(ast, node), 0, CodeSemantics.createControl()); + } + + return 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) { - long start = positions.getStartPosition(ast, node); - addToken(JavaTokenType.J_VARDEF, start, node.toString().length()); - - return super.visitVariable(node, p); + public Void visitVariable(VariableTree node, Void unused) { + if (!node.getName().contentEquals(ANONYMOUS_VARIABLE_NAME)) { + long start = positions.getStartPosition(ast, node); + 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) { - parsingExceptions.add(new ParsingException(file, "error while visiting %s".formatted(node))); - return super.visitErroneous(node, 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, CodeSemantics.createControl()); + return super.visitYield(node, null); } @Override - public Object visitYield(YieldTree 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_YIELD, start, end); - return super.visitYield(node, p); + addToken(JavaTokenType.J_DEFAULT, start, end, CodeSemantics.createControl()); + return super.visitDefaultCaseLabel(node, null); } @Override - public Object visitDefaultCaseLabel(DefaultCaseLabelTree node, Object p) { - long start = positions.getStartPosition(ast, node); - long end = positions.getEndPosition(ast, node); - addToken(JavaTokenType.J_DEFAULT, start, end); - return super.visitDefaultCaseLabel(node, p); + 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..e54955781 --- /dev/null +++ b/languages/java/src/test/java/de/jplag/java/JavaLanguageTest.java @@ -0,0 +1,85 @@ +package de.jplag.java; + +import static de.jplag.java.JavaTokenType.J_APPLY; +import static de.jplag.java.JavaTokenType.J_ARRAY_INIT_BEGIN; +import static de.jplag.java.JavaTokenType.J_ARRAY_INIT_END; +import static de.jplag.java.JavaTokenType.J_ASSIGN; +import static de.jplag.java.JavaTokenType.J_CATCH_BEGIN; +import static de.jplag.java.JavaTokenType.J_CATCH_END; +import static de.jplag.java.JavaTokenType.J_CLASS_BEGIN; +import static de.jplag.java.JavaTokenType.J_CLASS_END; +import static de.jplag.java.JavaTokenType.J_COND; +import static de.jplag.java.JavaTokenType.J_FINALLY_BEGIN; +import static de.jplag.java.JavaTokenType.J_FINALLY_END; +import static de.jplag.java.JavaTokenType.J_IF_BEGIN; +import static de.jplag.java.JavaTokenType.J_IF_END; +import static de.jplag.java.JavaTokenType.J_IMPORT; +import static de.jplag.java.JavaTokenType.J_LOOP_BEGIN; +import static de.jplag.java.JavaTokenType.J_LOOP_END; +import static de.jplag.java.JavaTokenType.J_METHOD_BEGIN; +import static de.jplag.java.JavaTokenType.J_METHOD_END; +import static de.jplag.java.JavaTokenType.J_NEWARRAY; +import static de.jplag.java.JavaTokenType.J_NEWCLASS; +import static de.jplag.java.JavaTokenType.J_PACKAGE; +import static de.jplag.java.JavaTokenType.J_RECORD_BEGIN; +import static de.jplag.java.JavaTokenType.J_RECORD_END; +import static de.jplag.java.JavaTokenType.J_RETURN; +import static de.jplag.java.JavaTokenType.J_THROW; +import static de.jplag.java.JavaTokenType.J_TRY_BEGIN; +import static de.jplag.java.JavaTokenType.J_TRY_END; +import static de.jplag.java.JavaTokenType.J_VARDEF; + +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); + + collector.testFile("PatternMatching.java", "PatternMatchingManual.java").testSourceCoverage().testTokenSequence(J_CLASS_BEGIN, J_RECORD_BEGIN, + J_VARDEF, J_RECORD_END, J_METHOD_BEGIN, J_VARDEF, J_NEWCLASS, J_IF_BEGIN, J_VARDEF, J_IF_END, J_METHOD_END, J_CLASS_END); + + collector.testFile("StringConcat.java", "StringTemplate.java").testSourceCoverage().testTokenSequence(J_CLASS_BEGIN, J_METHOD_BEGIN, J_VARDEF, + J_VARDEF, J_VARDEF, J_APPLY, J_METHOD_END, J_CLASS_END); + + collector.testFile("AnonymousVariables.java").testTokenSequence(J_CLASS_BEGIN, J_METHOD_BEGIN, J_VARDEF, J_IF_BEGIN, J_IF_END, J_METHOD_END, + J_CLASS_END); + } + + @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/AnonymousVariables.java b/languages/java/src/test/resources/de/jplag/java/AnonymousVariables.java new file mode 100644 index 000000000..41dd49238 --- /dev/null +++ b/languages/java/src/test/resources/de/jplag/java/AnonymousVariables.java @@ -0,0 +1,8 @@ +public class AnonymousVariables { + public void test(Object o) { + String _ = ""; + + if (o instanceof String _) { + } + } +} \ No newline at end of file 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/de/jplag/java/PatternMatching.java b/languages/java/src/test/resources/de/jplag/java/PatternMatching.java new file mode 100644 index 000000000..1a0eeb28f --- /dev/null +++ b/languages/java/src/test/resources/de/jplag/java/PatternMatching.java @@ -0,0 +1,10 @@ +public class PatternMatchingManual { + private static final record Test(int x) { + } + + public void test() { + Object a = new Test(1); + if (a instanceof Test testA) { + } + } +} \ No newline at end of file diff --git a/languages/java/src/test/resources/de/jplag/java/PatternMatchingManual.java b/languages/java/src/test/resources/de/jplag/java/PatternMatchingManual.java new file mode 100644 index 000000000..c6a9dd446 --- /dev/null +++ b/languages/java/src/test/resources/de/jplag/java/PatternMatchingManual.java @@ -0,0 +1,11 @@ +public class PatternMatchingManual { + private static final record Test(int x) { + } + + public void test() { + Object a = new Test(1); + if (a instanceof Test) { + Test testA = (Test) a; + } + } +} \ No newline at end of file diff --git a/languages/java/src/test/resources/de/jplag/java/StringConcat.java b/languages/java/src/test/resources/de/jplag/java/StringConcat.java new file mode 100644 index 000000000..74bb33f32 --- /dev/null +++ b/languages/java/src/test/resources/de/jplag/java/StringConcat.java @@ -0,0 +1,8 @@ +public class StringConcat { + void test() { + int param1 = 1; + String param2 = "test"; + + String result = "prefix " + param1 + " infix " + param2.length() + "suffix"; + } +} \ No newline at end of file diff --git a/languages/java/src/test/resources/de/jplag/java/StringTemplate.java b/languages/java/src/test/resources/de/jplag/java/StringTemplate.java new file mode 100644 index 000000000..113a5a629 --- /dev/null +++ b/languages/java/src/test/resources/de/jplag/java/StringTemplate.java @@ -0,0 +1,8 @@ +public class StringTemplate { + void test() { + int param1 = 1; + String param2 = "test"; + + String result = STR."prefix \{param1} infix + \{param2.length()} suffix"; + } +} \ No newline at end of file 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/javascript/README.md b/languages/javascript/README.md new file mode 100644 index 000000000..4314a36f9 --- /dev/null +++ b/languages/javascript/README.md @@ -0,0 +1,4 @@ +# JPlag TypeScript language module +All things mentioned in the [TypeScript README](../typescript/README.md) apply. + +This is a wrapper for the TypeScript frontend, to explicitly only parse JavaScript files. \ No newline at end of file diff --git a/languages/javascript/pom.xml b/languages/javascript/pom.xml new file mode 100644 index 000000000..3b6eab23c --- /dev/null +++ b/languages/javascript/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + + + de.jplag + languages + ${revision} + + javascript + + + + org.antlr + antlr4-runtime + + + de.jplag + language-antlr-utils + ${revision} + compile + + + de.jplag + typescript + ${revision} + compile + + + de.jplag + language-testutils + ${revision} + test + + + + + + + org.antlr + antlr4-maven-plugin + + + + antlr4 + + + + + + + diff --git a/languages/javascript/src/main/java/de/jplag/javascript/JavaScriptLanguage.java b/languages/javascript/src/main/java/de/jplag/javascript/JavaScriptLanguage.java new file mode 100644 index 000000000..bd07ba7f4 --- /dev/null +++ b/languages/javascript/src/main/java/de/jplag/javascript/JavaScriptLanguage.java @@ -0,0 +1,30 @@ +package de.jplag.javascript; + +import org.kohsuke.MetaInfServices; + +import de.jplag.typescript.TypeScriptLanguage; + +/** + * Represents the JavaScript Language as a variance of TypeScript + */ +@MetaInfServices(de.jplag.Language.class) +public class JavaScriptLanguage extends TypeScriptLanguage { + + private static final String IDENTIFIER = "javascript"; + private static final String NAME = "JavaScript"; + + @Override + public String getIdentifier() { + return IDENTIFIER; + } + + @Override + public String[] suffixes() { + return new String[] {".js"}; + } + + @Override + public String getName() { + return NAME; + } +} diff --git a/languages/javascript/src/test/java/de/jplag/javascript/JavaScriptLanguageTest.java b/languages/javascript/src/test/java/de/jplag/javascript/JavaScriptLanguageTest.java new file mode 100644 index 000000000..915f4899c --- /dev/null +++ b/languages/javascript/src/test/java/de/jplag/javascript/JavaScriptLanguageTest.java @@ -0,0 +1,38 @@ +package de.jplag.javascript; + +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; +import de.jplag.typescript.TypeScriptTokenType; + +public class JavaScriptLanguageTest extends LanguageModuleTest { + + public JavaScriptLanguageTest() { + super(new JavaScriptLanguage(), 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/javascript/src/test/resources/de/jplag/javascript/allJSTokens.js b/languages/javascript/src/test/resources/de/jplag/javascript/allJSTokens.js new file mode 100644 index 000000000..315b9d965 --- /dev/null +++ b/languages/javascript/src/test/resources/de/jplag/javascript/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/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..f6162a499 100644 --- a/languages/kotlin/pom.xml +++ b/languages/kotlin/pom.xml @@ -14,6 +14,11 @@ org.antlr antlr4-runtime + + de.jplag + language-antlr-utils + ${revision} + 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..d0dae5d67 --- /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 de.jplag.antlr.AbstractAntlrListener; +import de.jplag.kotlin.grammar.KotlinParser; +import de.jplag.kotlin.grammar.KotlinParser.AnonymousInitializerContext; +import de.jplag.kotlin.grammar.KotlinParser.AssignmentOperatorContext; +import de.jplag.kotlin.grammar.KotlinParser.CallSuffixContext; +import de.jplag.kotlin.grammar.KotlinParser.CatchBodyContext; +import de.jplag.kotlin.grammar.KotlinParser.CatchStatementContext; +import de.jplag.kotlin.grammar.KotlinParser.ClassBodyContext; +import de.jplag.kotlin.grammar.KotlinParser.ClassDeclarationContext; +import de.jplag.kotlin.grammar.KotlinParser.ClassParameterContext; +import de.jplag.kotlin.grammar.KotlinParser.CompanionObjectContext; +import de.jplag.kotlin.grammar.KotlinParser.ConstructorInvocationContext; +import de.jplag.kotlin.grammar.KotlinParser.ControlStructureBodyContext; +import de.jplag.kotlin.grammar.KotlinParser.DoWhileExpressionContext; +import de.jplag.kotlin.grammar.KotlinParser.EnumClassBodyContext; +import de.jplag.kotlin.grammar.KotlinParser.EnumEntryContext; +import de.jplag.kotlin.grammar.KotlinParser.FinallyBodyContext; +import de.jplag.kotlin.grammar.KotlinParser.FinallyStatementContext; +import de.jplag.kotlin.grammar.KotlinParser.ForExpressionContext; +import de.jplag.kotlin.grammar.KotlinParser.FunctionBodyContext; +import de.jplag.kotlin.grammar.KotlinParser.FunctionDeclarationContext; +import de.jplag.kotlin.grammar.KotlinParser.FunctionLiteralContext; +import de.jplag.kotlin.grammar.KotlinParser.FunctionValueParameterContext; +import de.jplag.kotlin.grammar.KotlinParser.GetterContext; +import de.jplag.kotlin.grammar.KotlinParser.IfExpressionContext; +import de.jplag.kotlin.grammar.KotlinParser.ImportHeaderContext; +import de.jplag.kotlin.grammar.KotlinParser.InitBlockContext; +import de.jplag.kotlin.grammar.KotlinParser.ObjectDeclarationContext; +import de.jplag.kotlin.grammar.KotlinParser.PackageHeaderContext; +import de.jplag.kotlin.grammar.KotlinParser.PrimaryConstructorContext; +import de.jplag.kotlin.grammar.KotlinParser.PropertyDeclarationContext; +import de.jplag.kotlin.grammar.KotlinParser.SecondaryConstructorContext; +import de.jplag.kotlin.grammar.KotlinParser.SetterContext; +import de.jplag.kotlin.grammar.KotlinParser.TryBodyContext; +import de.jplag.kotlin.grammar.KotlinParser.TryExpressionContext; +import de.jplag.kotlin.grammar.KotlinParser.TypeParameterContext; +import de.jplag.kotlin.grammar.KotlinParser.VariableDeclarationContext; +import de.jplag.kotlin.grammar.KotlinParser.WhenConditionContext; +import de.jplag.kotlin.grammar.KotlinParser.WhenExpressionContext; +import de.jplag.kotlin.grammar.KotlinParser.WhileExpressionContext; + +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..ce8762742 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,35 @@ 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.CharStreams; +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 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/cpp2/pom.xml b/languages/llvmir/pom.xml similarity index 82% rename from languages/cpp2/pom.xml rename to languages/llvmir/pom.xml index 7339e6167..c5306fb4c 100644 --- a/languages/cpp2/pom.xml +++ b/languages/llvmir/pom.xml @@ -1,18 +1,24 @@ 4.0.0 + de.jplag languages ${revision} - cpp2 + llvmir org.antlr antlr4-runtime + + de.jplag + language-antlr-utils + ${revision} + 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..9ce933926 --- /dev/null +++ b/languages/llvmir/src/main/java/de/jplag/llvmir/LLVMIRListener.java @@ -0,0 +1,181 @@ +package de.jplag.llvmir; + +import static de.jplag.llvmir.LLVMIRTokenType.ADDITION; +import static de.jplag.llvmir.LLVMIRTokenType.ALLOCATION; +import static de.jplag.llvmir.LLVMIRTokenType.AND; +import static de.jplag.llvmir.LLVMIRTokenType.ARRAY; +import static de.jplag.llvmir.LLVMIRTokenType.ASSEMBLY; +import static de.jplag.llvmir.LLVMIRTokenType.ATOMIC_ORDERING; +import static de.jplag.llvmir.LLVMIRTokenType.ATOMIC_READ_MODIFY_WRITE; +import static de.jplag.llvmir.LLVMIRTokenType.BASIC_BLOCK_BEGIN; +import static de.jplag.llvmir.LLVMIRTokenType.BASIC_BLOCK_END; +import static de.jplag.llvmir.LLVMIRTokenType.BITCAST; +import static de.jplag.llvmir.LLVMIRTokenType.BRANCH; +import static de.jplag.llvmir.LLVMIRTokenType.CALL; +import static de.jplag.llvmir.LLVMIRTokenType.CALL_BRANCH; +import static de.jplag.llvmir.LLVMIRTokenType.CASE; +import static de.jplag.llvmir.LLVMIRTokenType.CATCH_PAD; +import static de.jplag.llvmir.LLVMIRTokenType.CATCH_RETURN; +import static de.jplag.llvmir.LLVMIRTokenType.CATCH_SWITCH; +import static de.jplag.llvmir.LLVMIRTokenType.CLAUSE; +import static de.jplag.llvmir.LLVMIRTokenType.CLEAN_UP_PAD; +import static de.jplag.llvmir.LLVMIRTokenType.CLEAN_UP_RETURN; +import static de.jplag.llvmir.LLVMIRTokenType.COMPARE_EXCHANGE; +import static de.jplag.llvmir.LLVMIRTokenType.COMPARISON; +import static de.jplag.llvmir.LLVMIRTokenType.CONDITIONAL_BRANCH; +import static de.jplag.llvmir.LLVMIRTokenType.CONVERSION; +import static de.jplag.llvmir.LLVMIRTokenType.DIVISION; +import static de.jplag.llvmir.LLVMIRTokenType.EXTRACT_ELEMENT; +import static de.jplag.llvmir.LLVMIRTokenType.EXTRACT_VALUE; +import static de.jplag.llvmir.LLVMIRTokenType.FENCE; +import static de.jplag.llvmir.LLVMIRTokenType.FILENAME; +import static de.jplag.llvmir.LLVMIRTokenType.FUNCTION_BODY_BEGIN; +import static de.jplag.llvmir.LLVMIRTokenType.FUNCTION_BODY_END; +import static de.jplag.llvmir.LLVMIRTokenType.FUNCTION_DECLARATION; +import static de.jplag.llvmir.LLVMIRTokenType.FUNCTION_DEFINITION; +import static de.jplag.llvmir.LLVMIRTokenType.GET_ELEMENT_POINTER; +import static de.jplag.llvmir.LLVMIRTokenType.GLOBAL_VARIABLE; +import static de.jplag.llvmir.LLVMIRTokenType.INSERT_ELEMENT; +import static de.jplag.llvmir.LLVMIRTokenType.INSERT_VALUE; +import static de.jplag.llvmir.LLVMIRTokenType.INVOKE; +import static de.jplag.llvmir.LLVMIRTokenType.LANDING_PAD; +import static de.jplag.llvmir.LLVMIRTokenType.LOAD; +import static de.jplag.llvmir.LLVMIRTokenType.MULTIPLICATION; +import static de.jplag.llvmir.LLVMIRTokenType.OR; +import static de.jplag.llvmir.LLVMIRTokenType.PHI; +import static de.jplag.llvmir.LLVMIRTokenType.REMAINDER; +import static de.jplag.llvmir.LLVMIRTokenType.RESUME; +import static de.jplag.llvmir.LLVMIRTokenType.RETURN; +import static de.jplag.llvmir.LLVMIRTokenType.SELECT; +import static de.jplag.llvmir.LLVMIRTokenType.SHIFT; +import static de.jplag.llvmir.LLVMIRTokenType.SHUFFLE_VECTOR; +import static de.jplag.llvmir.LLVMIRTokenType.STORE; +import static de.jplag.llvmir.LLVMIRTokenType.STRUCTURE; +import static de.jplag.llvmir.LLVMIRTokenType.SUBTRACTION; +import static de.jplag.llvmir.LLVMIRTokenType.SWITCH; +import static de.jplag.llvmir.LLVMIRTokenType.TYPE_DEFINITION; +import static de.jplag.llvmir.LLVMIRTokenType.VARIABLE_ARGUMENT; +import static de.jplag.llvmir.LLVMIRTokenType.VECTOR; +import static de.jplag.llvmir.LLVMIRTokenType.XOR; + +import de.jplag.antlr.AbstractAntlrListener; +import de.jplag.llvmir.grammar.LLVMIRParser.*; + +/** + * 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..0365236e0 --- /dev/null +++ b/languages/llvmir/src/main/java/de/jplag/llvmir/LLVMIRParserAdapter.java @@ -0,0 +1,39 @@ +package de.jplag.llvmir; + +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.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..1a2c7e68b --- /dev/null +++ b/languages/llvmir/src/test/java/de/jplag/llvmir/LLVMIRLanguageTest.java @@ -0,0 +1,46 @@ +package de.jplag.llvmir; + +import static de.jplag.llvmir.LLVMIRTokenType.CATCH_PAD; +import static de.jplag.llvmir.LLVMIRTokenType.CATCH_RETURN; +import static de.jplag.llvmir.LLVMIRTokenType.CATCH_SWITCH; +import static de.jplag.llvmir.LLVMIRTokenType.CLEAN_UP_PAD; +import static de.jplag.llvmir.LLVMIRTokenType.CLEAN_UP_RETURN; + +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 c233fb95e..840542e84 100644 --- a/languages/pom.xml +++ b/languages/pom.xml @@ -9,11 +9,12 @@ languages pom + c cpp - cpp2 csharp emf-metamodel emf-metamodel-dynamic + emf-model golang java java-cpg @@ -23,8 +24,12 @@ rust scala scheme + scxml swift text + typescript + javascript + 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 80% 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..b5a8fd73f 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(); } @@ -41,7 +41,7 @@ public int minimumTokenMatch() { } @Override - public List parse(Set files) throws ParsingException { + public List parse(Set files, boolean normalize) throws ParsingException { return this.parser.parse(files); } } 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..0e24adf20 --- /dev/null +++ b/languages/python-3/src/main/java/de/jplag/python3/grammar/Python3LexerBase.java @@ -0,0 +1,138 @@ +package de.jplag.python3.grammar; + +import java.util.Deque; +import java.util.LinkedList; + +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.CommonToken; +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.Token; + +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..44b5926a4 --- /dev/null +++ b/languages/python-3/src/main/java/de/jplag/python3/grammar/Python3ParserBase.java @@ -0,0 +1,18 @@ +package de.jplag.python3.grammar; + +import org.antlr.v4.runtime.Parser; +import org.antlr.v4.runtime.TokenStream; + +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/PythonLanguageTest.java b/languages/python-3/src/test/java/de/jplag/python3/PythonLanguageTest.java new file mode 100644 index 000000000..5d17ef33f --- /dev/null +++ b/languages/python-3/src/test/java/de/jplag/python3/PythonLanguageTest.java @@ -0,0 +1,42 @@ +package de.jplag.python3; + +import de.jplag.testutils.LanguageModuleTest; +import de.jplag.testutils.datacollector.TestDataCollector; +import de.jplag.testutils.datacollector.TestSourceIgnoredLinesCollector; + +/** + * Tests for the python language module. The following tests are included: + *

+ *

    + *
  • test all tokens occur in test_utils.py.
  • + *
  • test exact sequences for log.py and unicode.py.
  • + *
  • test that all relevant lines are covered in all test files.
  • + *
+ */ +public class PythonLanguageTest extends LanguageModuleTest { + public PythonLanguageTest() { + super(new PythonLanguage(), Python3TokenType.class); + } + + @Override + protected void collectTestData(TestDataCollector collector) { + collector.testFile("test_utils.py").testCoverages(); + + collector.testFile("base_features.py", "streams.py").testSourceCoverage(); + + collector.testFile("log.py").testSourceCoverage().testTokenSequence(Python3TokenType.IMPORT, Python3TokenType.ASSIGN, Python3TokenType.ARRAY, + Python3TokenType.APPLY); + + collector.testFile("unicode.py").testSourceCoverage().testTokenSequence(Python3TokenType.ASSIGN); + } + + @Override + protected void configureIgnoredLines(TestSourceIgnoredLinesCollector collector) { + collector.ignoreMultipleLines("\"\"\""); + + collector.ignoreLinesByPrefix("else:"); + collector.ignoreLinesByPrefix("elif"); + collector.ignoreLinesByPrefix("#"); + collector.ignoreLinesByPrefix("pass"); + } +} 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 86% 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..d09e23b72 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(); } @@ -46,7 +46,7 @@ public int minimumTokenMatch() { } @Override - public List parse(Set files) throws ParsingException { + public List parse(Set files, boolean normalize) throws ParsingException { return parserAdapter.parse(files); } } 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 85% 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..50f0826e0 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(); } @@ -47,7 +47,7 @@ public int minimumTokenMatch() { } @Override - public List parse(Set files) throws ParsingException { + public List parse(Set files, boolean normalize) throws ParsingException { return parserAdapter.parse(files); } } 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/main/java/de/jplag/rust/grammar/RustLexerBase.java b/languages/rust/src/main/java/de/jplag/rust/grammar/RustLexerBase.java index 87975ddba..cf99293cd 100644 --- a/languages/rust/src/main/java/de/jplag/rust/grammar/RustLexerBase.java +++ b/languages/rust/src/main/java/de/jplag/rust/grammar/RustLexerBase.java @@ -50,8 +50,9 @@ public boolean floatDotPossible() { private boolean lookAheadMatches(String expected) { for (int charIndex = 0; charIndex < expected.length(); charIndex++) { - if (_input.LA(charIndex + 1) != expected.charAt(charIndex)) + if (_input.LA(charIndex + 1) != expected.charAt(charIndex)) { return false; + } } return true; } @@ -61,9 +62,7 @@ private boolean lookAheadMatchesOneOf(String... expected) { } public boolean floatLiteralPossible() { - if (this.currentToken == null || this.currentToken.getType() != RustLexer.DOT) { - return true; - } else if (this.previousToken == null) { + if (this.currentToken == null || this.currentToken.getType() != RustLexer.DOT || (this.previousToken == null)) { return true; } 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..7c43463dc 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.15
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 71% 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..424b0f733 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") @@ -20,5 +20,5 @@ class Language extends de.jplag.Language { override def minimumTokenMatch = 8 - override def parse(files: util.Set[File]): java.util.List[Token] = this.parser.parse(files.asScala.toSet).asJava + override def parse(files: util.Set[File], normalize: Boolean): java.util.List[Token] = this.parser.parse(files.asScala.toSet).asJava } 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..2f0660b54 100644 --- a/languages/scala/src/test/java/de/jplag/scala/ScalaLanguageTest.java +++ b/languages/scala/src/test/java/de/jplag/scala/ScalaLanguageTest.java @@ -19,6 +19,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import de.jplag.ParsingException; import de.jplag.SharedTokenType; import de.jplag.Token; import de.jplag.TokenPrinter; @@ -49,15 +50,15 @@ 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 - void parseTestFiles() { + void parseTestFiles() throws ParsingException { for (String fileName : testFiles) { List tokens = language.parse(Set.of(new File(testFileLocation, fileName))); String output = TokenPrinter.printTokens(tokens, testFileLocation); @@ -110,7 +111,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 81% 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..0ebbf4ef9 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(); } @@ -40,7 +40,7 @@ public int minimumTokenMatch() { } @Override - public List parse(Set files) throws ParsingException { + public List parse(Set files, boolean normalize) throws ParsingException { return this.parser.parse(files); } } 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..37a3ab4dd --- /dev/null +++ b/languages/scxml/pom.xml @@ -0,0 +1,19 @@ + + + 4.0.0 + + de.jplag + languages + ${revision} + + scxml + + + + org.assertj + assertj-core + 3.25.3 + 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..ec6316f4d --- /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, boolean normalize) 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..09bab656e --- /dev/null +++ b/languages/scxml/src/main/java/de/jplag/scxml/parser/HandcraftedScxmlTokenGenerator.java @@ -0,0 +1,75 @@ +package de.jplag.scxml.parser; + +import static de.jplag.scxml.ScxmlTokenType.GUARDED_TRANSITION; +import static de.jplag.scxml.ScxmlTokenType.INITIAL_REGION; +import static de.jplag.scxml.ScxmlTokenType.INITIAL_STATE; +import static de.jplag.scxml.ScxmlTokenType.REGION; +import static de.jplag.scxml.ScxmlTokenType.STATE; +import static de.jplag.scxml.ScxmlTokenType.STATE_END; +import static de.jplag.scxml.ScxmlTokenType.TIMED_TRANSITION; +import static de.jplag.scxml.ScxmlTokenType.TRANSITION; +import static de.jplag.scxml.ScxmlTokenType.TRANSITION_END; + +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..ba94ac2ed --- /dev/null +++ b/languages/scxml/src/main/java/de/jplag/scxml/parser/SimpleScxmlTokenGenerator.java @@ -0,0 +1,192 @@ +package de.jplag.scxml.parser; + +import static de.jplag.scxml.ScxmlTokenType.ACTION_END; +import static de.jplag.scxml.ScxmlTokenType.ASSIGNMENT; +import static de.jplag.scxml.ScxmlTokenType.CANCEL; +import static de.jplag.scxml.ScxmlTokenType.ELSE; +import static de.jplag.scxml.ScxmlTokenType.ELSE_END; +import static de.jplag.scxml.ScxmlTokenType.ELSE_IF; +import static de.jplag.scxml.ScxmlTokenType.ELSE_IF_END; +import static de.jplag.scxml.ScxmlTokenType.FOREACH; +import static de.jplag.scxml.ScxmlTokenType.IF; +import static de.jplag.scxml.ScxmlTokenType.IF_END; +import static de.jplag.scxml.ScxmlTokenType.ON_ENTRY; +import static de.jplag.scxml.ScxmlTokenType.ON_EXIT; +import static de.jplag.scxml.ScxmlTokenType.RAISE; +import static de.jplag.scxml.ScxmlTokenType.SCRIPT; +import static de.jplag.scxml.ScxmlTokenType.SEND; +import static de.jplag.scxml.ScxmlTokenType.STATE; +import static de.jplag.scxml.ScxmlTokenType.STATE_END; +import static de.jplag.scxml.ScxmlTokenType.TRANSITION; +import static de.jplag.scxml.ScxmlTokenType.TRANSITION_END; +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.Action; +import de.jplag.scxml.parser.model.executable_content.Cancel; +import de.jplag.scxml.parser.model.executable_content.Else; +import de.jplag.scxml.parser.model.executable_content.ElseIf; +import de.jplag.scxml.parser.model.executable_content.ExecutableContent; +import de.jplag.scxml.parser.model.executable_content.If; +import de.jplag.scxml.parser.model.executable_content.Send; +import de.jplag.scxml.parser.model.executable_content.SimpleExecutableContent; +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..4b4632382 --- /dev/null +++ b/languages/scxml/src/main/java/de/jplag/scxml/parser/model/executable_content/ExecutableContent.java @@ -0,0 +1,114 @@ +package de.jplag.scxml.parser.model.executable_content; + +import static de.jplag.scxml.parser.model.executable_content.SimpleExecutableContent.Type.ASSIGNMENT; +import static de.jplag.scxml.parser.model.executable_content.SimpleExecutableContent.Type.FOREACH; +import static de.jplag.scxml.parser.model.executable_content.SimpleExecutableContent.Type.LOG; +import static de.jplag.scxml.parser.model.executable_content.SimpleExecutableContent.Type.RAISE; +import static de.jplag.scxml.parser.model.executable_content.SimpleExecutableContent.Type.SCRIPT; + +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/JPlagSwiftListener.java b/languages/swift/src/main/java/de/jplag/swift/JPlagSwiftListener.java index b52900c77..90e1e8249 100644 --- a/languages/swift/src/main/java/de/jplag/swift/JPlagSwiftListener.java +++ b/languages/swift/src/main/java/de/jplag/swift/JPlagSwiftListener.java @@ -1,10 +1,106 @@ package de.jplag.swift; -import static de.jplag.swift.SwiftTokenType.*; +import static de.jplag.swift.SwiftTokenType.ASSIGNMENT; +import static de.jplag.swift.SwiftTokenType.BREAK; +import static de.jplag.swift.SwiftTokenType.CATCH_BODY_BEGIN; +import static de.jplag.swift.SwiftTokenType.CATCH_BODY_END; +import static de.jplag.swift.SwiftTokenType.CLASS_BODY_BEGIN; +import static de.jplag.swift.SwiftTokenType.CLASS_BODY_END; +import static de.jplag.swift.SwiftTokenType.CLASS_DECLARATION; +import static de.jplag.swift.SwiftTokenType.CLOSURE_BODY_BEGIN; +import static de.jplag.swift.SwiftTokenType.CLOSURE_BODY_END; +import static de.jplag.swift.SwiftTokenType.CONTINUE; +import static de.jplag.swift.SwiftTokenType.DEFER_BODY_BEGIN; +import static de.jplag.swift.SwiftTokenType.DEFER_BODY_END; +import static de.jplag.swift.SwiftTokenType.DO_TRY_BODY_BEGIN; +import static de.jplag.swift.SwiftTokenType.DO_TRY_BODY_END; +import static de.jplag.swift.SwiftTokenType.ENUM_BODY_BEGIN; +import static de.jplag.swift.SwiftTokenType.ENUM_BODY_END; +import static de.jplag.swift.SwiftTokenType.ENUM_DECLARATION; +import static de.jplag.swift.SwiftTokenType.ENUM_LITERAL; +import static de.jplag.swift.SwiftTokenType.FALLTHROUGH; +import static de.jplag.swift.SwiftTokenType.FOR_BODY_BEGIN; +import static de.jplag.swift.SwiftTokenType.FOR_BODY_END; +import static de.jplag.swift.SwiftTokenType.FUNCTION; +import static de.jplag.swift.SwiftTokenType.FUNCTION_BODY_BEGIN; +import static de.jplag.swift.SwiftTokenType.FUNCTION_BODY_END; +import static de.jplag.swift.SwiftTokenType.FUNCTION_CALL; +import static de.jplag.swift.SwiftTokenType.FUNCTION_PARAMETER; +import static de.jplag.swift.SwiftTokenType.IF_BODY_BEGIN; +import static de.jplag.swift.SwiftTokenType.IF_BODY_END; +import static de.jplag.swift.SwiftTokenType.IMPORT; +import static de.jplag.swift.SwiftTokenType.PROPERTY_ACCESSOR_BEGIN; +import static de.jplag.swift.SwiftTokenType.PROPERTY_ACCESSOR_END; +import static de.jplag.swift.SwiftTokenType.PROPERTY_DECLARATION; +import static de.jplag.swift.SwiftTokenType.PROTOCOL_BODY_BEGIN; +import static de.jplag.swift.SwiftTokenType.PROTOCOL_BODY_END; +import static de.jplag.swift.SwiftTokenType.PROTOCOL_DECLARATION; +import static de.jplag.swift.SwiftTokenType.REPEAT_WHILE_BODY_BEGIN; +import static de.jplag.swift.SwiftTokenType.REPEAT_WHILE_BODY_END; +import static de.jplag.swift.SwiftTokenType.RETURN; +import static de.jplag.swift.SwiftTokenType.STRUCT_BODY_BEGIN; +import static de.jplag.swift.SwiftTokenType.STRUCT_BODY_END; +import static de.jplag.swift.SwiftTokenType.STRUCT_DECLARATION; +import static de.jplag.swift.SwiftTokenType.SWITCH_BODY_BEGIN; +import static de.jplag.swift.SwiftTokenType.SWITCH_BODY_END; +import static de.jplag.swift.SwiftTokenType.SWITCH_CASE; +import static de.jplag.swift.SwiftTokenType.THROW; +import static de.jplag.swift.SwiftTokenType.WHILE_BODY_BEGIN; +import static de.jplag.swift.SwiftTokenType.WHILE_BODY_END; import org.antlr.v4.runtime.Token; -import de.jplag.swift.grammar.Swift5Parser.*; +import de.jplag.swift.grammar.Swift5Parser.Binary_operatorContext; +import de.jplag.swift.grammar.Swift5Parser.Break_statementContext; +import de.jplag.swift.grammar.Swift5Parser.Catch_clauseContext; +import de.jplag.swift.grammar.Swift5Parser.Class_bodyContext; +import de.jplag.swift.grammar.Swift5Parser.Class_declarationContext; +import de.jplag.swift.grammar.Swift5Parser.Closure_expressionContext; +import de.jplag.swift.grammar.Swift5Parser.Code_blockContext; +import de.jplag.swift.grammar.Swift5Parser.Constant_declarationContext; +import de.jplag.swift.grammar.Swift5Parser.Continue_statementContext; +import de.jplag.swift.grammar.Swift5Parser.Defer_statementContext; +import de.jplag.swift.grammar.Swift5Parser.DidSet_clauseContext; +import de.jplag.swift.grammar.Swift5Parser.Do_blockContext; +import de.jplag.swift.grammar.Swift5Parser.Else_clauseContext; +import de.jplag.swift.grammar.Swift5Parser.Enum_nameContext; +import de.jplag.swift.grammar.Swift5Parser.Fallthrough_statementContext; +import de.jplag.swift.grammar.Swift5Parser.For_in_statementContext; +import de.jplag.swift.grammar.Swift5Parser.Function_bodyContext; +import de.jplag.swift.grammar.Swift5Parser.Function_call_suffixContext; +import de.jplag.swift.grammar.Swift5Parser.Function_nameContext; +import de.jplag.swift.grammar.Swift5Parser.Function_resultContext; +import de.jplag.swift.grammar.Swift5Parser.Getter_clauseContext; +import de.jplag.swift.grammar.Swift5Parser.Getter_setter_blockContext; +import de.jplag.swift.grammar.Swift5Parser.Guard_statementContext; +import de.jplag.swift.grammar.Swift5Parser.If_statementContext; +import de.jplag.swift.grammar.Swift5Parser.Import_declarationContext; +import de.jplag.swift.grammar.Swift5Parser.InitializerContext; +import de.jplag.swift.grammar.Swift5Parser.Initializer_bodyContext; +import de.jplag.swift.grammar.Swift5Parser.Initializer_declarationContext; +import de.jplag.swift.grammar.Swift5Parser.ParameterContext; +import de.jplag.swift.grammar.Swift5Parser.Protocol_bodyContext; +import de.jplag.swift.grammar.Swift5Parser.Protocol_declarationContext; +import de.jplag.swift.grammar.Swift5Parser.Protocol_initializer_declarationContext; +import de.jplag.swift.grammar.Swift5Parser.Protocol_property_declarationContext; +import de.jplag.swift.grammar.Swift5Parser.Raw_value_assignmentContext; +import de.jplag.swift.grammar.Swift5Parser.Raw_value_style_enumContext; +import de.jplag.swift.grammar.Swift5Parser.Raw_value_style_enum_caseContext; +import de.jplag.swift.grammar.Swift5Parser.Raw_value_style_enum_membersContext; +import de.jplag.swift.grammar.Swift5Parser.Repeat_while_statementContext; +import de.jplag.swift.grammar.Swift5Parser.Return_statementContext; +import de.jplag.swift.grammar.Swift5Parser.Setter_clauseContext; +import de.jplag.swift.grammar.Swift5Parser.Struct_bodyContext; +import de.jplag.swift.grammar.Swift5Parser.Struct_declarationContext; +import de.jplag.swift.grammar.Swift5Parser.Switch_caseContext; +import de.jplag.swift.grammar.Swift5Parser.Switch_statementContext; +import de.jplag.swift.grammar.Swift5Parser.Throw_statementContext; +import de.jplag.swift.grammar.Swift5Parser.Union_style_enumContext; +import de.jplag.swift.grammar.Swift5Parser.Union_style_enum_caseContext; +import de.jplag.swift.grammar.Swift5Parser.Union_style_enum_membersContext; +import de.jplag.swift.grammar.Swift5Parser.Variable_declarationContext; +import de.jplag.swift.grammar.Swift5Parser.While_statementContext; +import de.jplag.swift.grammar.Swift5Parser.WillSet_clauseContext; import de.jplag.swift.grammar.Swift5ParserBaseListener; public class JPlagSwiftListener extends Swift5ParserBaseListener { 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 85% 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..87e13269f 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(); } @@ -47,7 +47,7 @@ public int minimumTokenMatch() { } @Override - public List parse(Set files) throws ParsingException { + public List parse(Set files, boolean normalize) throws ParsingException { return parserAdapter.parse(files); } } 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/main/java/de/jplag/swift/grammar/SwiftSupport.java b/languages/swift/src/main/java/de/jplag/swift/grammar/SwiftSupport.java index 45c1a0dca..9da0d5b09 100644 --- a/languages/swift/src/main/java/de/jplag/swift/grammar/SwiftSupport.java +++ b/languages/swift/src/main/java/de/jplag/swift/grammar/SwiftSupport.java @@ -162,7 +162,6 @@ public static boolean isOperatorCharacter(Token token) { public static boolean isOpNext(TokenStream tokens) { int start = tokens.index(); - Token lt = tokens.get(start); int stop = getLastOpTokenIndex(tokens); return stop != -1; // System.out.printf("isOpNext: i=%d t='%s'", start, lt.getText()); 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 86% 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..572713009 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(); } @@ -45,7 +45,7 @@ public int minimumTokenMatch() { } @Override - public List parse(Set files) throws ParsingException { + public List parse(Set files, boolean normalize) throws ParsingException { return parserAdapter.parse(files); } } 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..9fa5ad514 --- /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(boolean normalize) { + 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..5a65d7c42 --- /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.Else; +import static de.jplag.typescript.grammar.TypeScriptParser.Export; + +import de.jplag.antlr.AbstractAntlrListener; +import de.jplag.typescript.grammar.TypeScriptParser.ArgumentsContext; +import de.jplag.typescript.grammar.TypeScriptParser.ArrowFunctionDeclarationContext; +import de.jplag.typescript.grammar.TypeScriptParser.AssignmentExpressionContext; +import de.jplag.typescript.grammar.TypeScriptParser.BreakStatementContext; +import de.jplag.typescript.grammar.TypeScriptParser.CaseClauseContext; +import de.jplag.typescript.grammar.TypeScriptParser.CatchProductionContext; +import de.jplag.typescript.grammar.TypeScriptParser.ClassDeclarationContext; +import de.jplag.typescript.grammar.TypeScriptParser.ConstructorDeclarationContext; +import de.jplag.typescript.grammar.TypeScriptParser.ContinueStatementContext; +import de.jplag.typescript.grammar.TypeScriptParser.DefaultClauseContext; +import de.jplag.typescript.grammar.TypeScriptParser.EnumDeclarationContext; +import de.jplag.typescript.grammar.TypeScriptParser.EnumMemberContext; +import de.jplag.typescript.grammar.TypeScriptParser.FinallyProductionContext; +import de.jplag.typescript.grammar.TypeScriptParser.ForInStatementContext; +import de.jplag.typescript.grammar.TypeScriptParser.ForStatementContext; +import de.jplag.typescript.grammar.TypeScriptParser.ForVarStatementContext; +import de.jplag.typescript.grammar.TypeScriptParser.FunctionDeclarationContext; +import de.jplag.typescript.grammar.TypeScriptParser.FunctionExpressionDeclarationContext; +import de.jplag.typescript.grammar.TypeScriptParser.GetterSetterDeclarationExpressionContext; +import de.jplag.typescript.grammar.TypeScriptParser.IfStatementContext; +import de.jplag.typescript.grammar.TypeScriptParser.ImportStatementContext; +import de.jplag.typescript.grammar.TypeScriptParser.InterfaceDeclarationContext; +import de.jplag.typescript.grammar.TypeScriptParser.MethodDeclarationExpressionContext; +import de.jplag.typescript.grammar.TypeScriptParser.NamespaceDeclarationContext; +import de.jplag.typescript.grammar.TypeScriptParser.PostDecreaseExpressionContext; +import de.jplag.typescript.grammar.TypeScriptParser.PostIncrementExpressionContext; +import de.jplag.typescript.grammar.TypeScriptParser.PreDecreaseExpressionContext; +import de.jplag.typescript.grammar.TypeScriptParser.PreIncrementExpressionContext; +import de.jplag.typescript.grammar.TypeScriptParser.PropertyDeclarationExpressionContext; +import de.jplag.typescript.grammar.TypeScriptParser.PropertySetterContext; +import de.jplag.typescript.grammar.TypeScriptParser.PropertySignaturContext; +import de.jplag.typescript.grammar.TypeScriptParser.ReturnStatementContext; +import de.jplag.typescript.grammar.TypeScriptParser.SwitchStatementContext; +import de.jplag.typescript.grammar.TypeScriptParser.ThrowStatementContext; +import de.jplag.typescript.grammar.TypeScriptParser.TryStatementContext; +import de.jplag.typescript.grammar.TypeScriptParser.VariableDeclarationContext; +import de.jplag.typescript.grammar.TypeScriptParser.WhileStatementContext; + +/** + * 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..1d31eb1ca --- /dev/null +++ b/languages/typescript/src/main/java/de/jplag/typescript/TypeScriptTokenType.java @@ -0,0 +1,57 @@ +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; + + @Override + 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/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/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/package-lock.json b/package-lock.json new file mode 100644 index 000000000..791717fd3 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "JPlag", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} diff --git a/pom.xml b/pom.xml index 07d4e5ad0..dba35b8c0 100644 --- a/pom.xml +++ b/pom.xml @@ -72,20 +72,21 @@ ${maven.multiModuleProjectDirectory}/coverage-report/target/site/jacoco-aggregate/jacoco.xml - 17 - 17 - 2.35.0 - 2.0.7 - 5.9.2 + 21 + 21 + 2.43.0 + 2.0.12 + 5.10.2 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.36.0 + 1.0.0 - 4.3.0 + 5.0.0 @@ -116,7 +117,7 @@ edu.stanford.nlp stanford-corenlp - 4.5.3 + 4.5.6 @@ -133,13 +134,13 @@ org.kohsuke.metainf-services metainf-services - 1.9 + 1.11 com.fasterxml.jackson.core jackson-databind - 2.14.2 + 2.16.1 @@ -166,7 +167,7 @@ org.mockito mockito-core - 5.2.0 + 5.10.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.2.5 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.6.0 true resolveCiFriendliesOnly @@ -309,7 +310,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.3.0 + 3.5.0 add-source @@ -329,7 +330,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.5.0 + 3.6.3 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 @@ -421,6 +423,7 @@ languages language-api language-testutils + language-antlr-utils 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..dd9e51bf7 --- /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..b4eb63f65 --- /dev/null +++ b/report-viewer/.husky/pre-commit @@ -0,0 +1,2 @@ +cd ./report-viewer +npx lint-staged \ No newline at end of file diff --git a/report-viewer/.lintstagedrc.json b/report-viewer/.lintstagedrc.json new file mode 100644 index 000000000..980a246ef --- /dev/null +++ b/report-viewer/.lintstagedrc.json @@ -0,0 +1,7 @@ +{ + "*.ts": ["npx prettier --write", "npx eslint --max-warnings 0"], + "*.vue": ["npx prettier --write", "npx eslint --max-warnings 0"], + "*.js": ["npx prettier --write", "npx eslint --max-warnings 0"], + "*.html": ["npx prettier --write", "npx eslint --max-warnings 0"], + "*.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 3e2f820ff..b272d1fce 100644 --- a/report-viewer/package-lock.json +++ b/report-viewer/package-lock.json @@ -1,2134 +1,2014 @@ { "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", - "dependencies": { - "@highlightjs/vue-plugin": "^2.1.0", - "chart.js": "^3.9.1", + "version": "0.0.0", + "dependencies": { + "@fortawesome/fontawesome-svg-core": "^6.5.1", + "@fortawesome/free-brands-svg-icons": "^6.5.1", + "@fortawesome/free-regular-svg-icons": "^6.5.1", + "@fortawesome/free-solid-svg-icons": "^6.5.1", + "@fortawesome/vue-fontawesome": "^3.0.5", + "chart.js": "^4.4.1", + "chartjs-chart-graph": "^4.2.8", "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.3.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==", + "@playwright/test": "^1.40.1", + "@rushstack/eslint-patch": "^1.7.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^18.19.15", + "@vitejs/plugin-vue": "^5.0.4", + "@vue/eslint-config-prettier": "^9.0.0", + "@vue/eslint-config-typescript": "^12.0.0", + "@vue/test-utils": "^2.4.3", + "@vue/tsconfig": "^0.5.1", + "autoprefixer": "^10.4.16", + "eslint": "^8.56.0", + "eslint-plugin-vue": "^9.20.1", + "husky": "^9.0.11", + "jsdom": "^24.0.0", + "lint-staged": "^15.2.2", + "npm-run-all": "^4.1.5", + "postcss": "^8.4.35", + "prettier": "^3.2.5", + "prettier-plugin-tailwindcss": "^0.5.11", + "tailwindcss": "^3.4.1", + "typescript": "^5.3.3", + "vite": "^5.1.1", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } + }, + "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, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.0" - }, "engines": { - "node": ">=6.0.0" + "node": ">=0.10.0" } }, - "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "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": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" - }, "engines": { - "node": ">=6.9.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", - "dev": true, + "node_modules/@babel/parser": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", + "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", + "bin": { + "parser": "bin/babel-parser.js" + }, "engines": { - "node": ">=6.9.0" + "node": ">=6.0.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/@esbuild/aix-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "cpu": [ + "ppc64" + ], "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" - }, + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" + "node": ">=12" } }, - "node_modules/@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "node_modules/@esbuild/android-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.23.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "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-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "cpu": [ + "arm64" + ], "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-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "cpu": [ + "x64" + ], "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/darwin-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", + "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "cpu": [ + "arm64" + ], "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": [ + "darwin" + ], "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-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "cpu": [ + "x64" + ], "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/freebsd-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "regexpu-core": "^5.1.0" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=12" } }, - "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==", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "cpu": [ + "x64" + ], "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" + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "node_modules/@esbuild/linux-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "cpu": [ + "arm" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "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/linux-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "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-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "cpu": [ + "loong64" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, + "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-mips64el": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "cpu": [ + "mips64el" + ], "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-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "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-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-riscv64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "cpu": [ + "riscv64" + ], "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-s390x": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "cpu": [ + "s390x" + ], "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-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "cpu": [ + "x64" + ], "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/netbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "cpu": [ + "x64" + ], "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": [ + "netbsd" + ], "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/openbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "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": [ + "openbsd" + ], "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/sunos-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "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-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/win32-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "node_modules/@esbuild/win32-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "cpu": [ + "x64" + ], "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "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": { + "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/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/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true, "engines": { - "node": ">=6.9.0" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "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/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "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" + "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/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/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.0", - "@babel/types": "^7.17.0" - }, - "engines": { - "node": ">=6.9.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=6.9.0" + "node": "*" } }, - "node_modules/@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", - "bin": { - "parser": "bin/babel-parser.js" - }, + "node_modules/@eslint/js": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "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.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.1.tgz", + "integrity": "sha512-GkWzv+L6d2bI5f/Vk6ikJ9xtl7dfXtoRu3YGE6nq0p/FFqA1ebMOAWg3XgRyb0I6LYyYkiAo+3/KrwuBp8xG7A==", + "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.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.1.tgz", + "integrity": "sha512-MfRCYlQPXoLlpem+egxjfkEuP9UQswTrlCOsknus/NcMoblTH2g0jPrapbcIb04KGA7E2GZxbAccGZfWoYgsrQ==", + "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.5.1" }, "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-brands-svg-icons": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.5.1.tgz", + "integrity": "sha512-093l7DAkx0aEtBq66Sf19MgoZewv1zeY9/4C7vSKPO4qMwEsW/2VYTUTpBtLwfb9T2R73tXaRDPmE4UqLCYHfg==", + "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.5.1" }, "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-regular-svg-icons": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.5.1.tgz", + "integrity": "sha512-m6ShXn+wvqEU69wSP84coxLbNl7sGVZb+Ca+XZq6k30SzuP3X4TfPqtycgUh9ASwlNh5OfQCd8pDIWxl+O+LlQ==", + "hasInstallScript": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@fortawesome/fontawesome-common-types": "6.5.1" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=6" } }, - "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==", - "dev": true, + "node_modules/@fortawesome/free-solid-svg-icons": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.1.tgz", + "integrity": "sha512-S1PPfU3mIJa59biTtXJz1oI0+KAXW6bkAb31XKhxdxtuXDiUIFsih4JR1v5BbxY7hVHsD1RKq+jRkVRaf773NQ==", + "hasInstallScript": 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" + "@fortawesome/fontawesome-common-types": "6.5.1" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" + "node": ">=6" } }, - "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==", - "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_modules/@fortawesome/vue-fontawesome": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-3.0.6.tgz", + "integrity": "sha512-akrL7lTroyNpPkoHtvK2UpsMzJr6jXdHaQ0YdcwqDsB8jdwlpNHZYijpOUd9KJsARr+VB3WXY4EyObepqJ4ytQ==", "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@fortawesome/fontawesome-svg-core": "~1 || ~6", + "vue": ">= 3.0.0 < 4" } }, - "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==", + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=10.10.0" } }, - "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/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "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/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-json-strings": "^7.8.3" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "*" } }, - "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/@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-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - }, "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-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, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "dev": true }, - "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/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "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/@isaacs/cliui/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": { - "@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" - }, "engines": { - "node": ">=6.9.0" + "node": ">=12" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "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/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=6.9.0" + "node": ">=12" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "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/@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/helper-skip-transparent-expression-wrappers": "^7.18.6", - "@babel/plugin-syntax-optional-chaining": "^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-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/@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-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@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-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/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", "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" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=6.0.0" } }, - "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/@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-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": ">=6.0.0" } }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "node_modules/@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/@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/@jridgewell/trace-mapping": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", + "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "node_modules/@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/@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/@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/helper-plugin-utils": "^7.14.5" + "@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-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/@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" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 8" } }, - "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/@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.8.0" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">= 8" } }, - "node_modules/@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "node_modules/@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/@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/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, + "optional": true, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=14" } }, - "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/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "engines": { + "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-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/@playwright/test": { + "version": "1.41.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.41.2.tgz", + "integrity": "sha512-qQB9h7KbibJzrDpkXkYvsmiDJK14FULCCZgEcoe2AvFAS64oCirWTwzTlAYEbKaRxWs5TFesE1Na6izMv3HfGg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "playwright": "1.41.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "bin": { + "playwright": "cli.js" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=16" } }, - "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/@rollup/rollup-android-arm-eabi": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.6.tgz", + "integrity": "sha512-MVNXSSYN6QXOulbHpLMKYi60ppyO13W9my1qogeiAqtjb2yR4LSmfU2+POvDkLzhjYLXz9Rf9+9a3zFHW1Lecg==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "optional": true, + "os": [ + "android" + ] }, - "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/@rollup/rollup-android-arm64": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.6.tgz", + "integrity": "sha512-T14aNLpqJ5wzKNf5jEDpv5zgyIqcpn1MlwCrUXLrwoADr2RkWA0vOWP4XxbO9aiO3dvMCQICZdKeDrFl7UMClw==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "optional": true, + "os": [ + "android" + ] }, - "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/@rollup/rollup-darwin-arm64": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.6.tgz", + "integrity": "sha512-CqNNAyhRkTbo8VVZ5R85X73H3R5NX9ONnKbXuHisGWC0qRbTTxnF1U4V9NafzJbgGM0sHZpdO83pLPzq8uOZFw==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "optional": true, + "os": [ + "darwin" + ] }, - "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/@rollup/rollup-darwin-x64": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.6.tgz", + "integrity": "sha512-zRDtdJuRvA1dc9Mp6BWYqAsU5oeLixdfUvkTHuiYOHwqYuQ4YgSmi6+/lPvSsqc/I0Omw3DdICx4Tfacdzmhog==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "optional": true, + "os": [ + "darwin" + ] }, - "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/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.6.tgz", + "integrity": "sha512-oNk8YXDDnNyG4qlNb6is1ojTOGL/tRhbbKeE/YuccItzerEZT68Z9gHrY3ROh7axDc974+zYAPxK5SH0j/G+QQ==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "optional": true, + "os": [ + "linux" + ] }, - "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/@rollup/rollup-linux-arm64-gnu": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.6.tgz", + "integrity": "sha512-Z3O60yxPtuCYobrtzjo0wlmvDdx2qZfeAWTyfOjEDqd08kthDKexLpV97KfAeUXPosENKd8uyJMRDfFMxcYkDQ==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "optional": true, + "os": [ + "linux" + ] }, - "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/@rollup/rollup-linux-arm64-musl": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.6.tgz", + "integrity": "sha512-gpiG0qQJNdYEVad+1iAsGAbgAnZ8j07FapmnIAQgODKcOTjLEWM9sRb+MbQyVsYCnA0Im6M6QIq6ax7liws6eQ==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "optional": true, + "os": [ + "linux" + ] }, - "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/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.6.tgz", + "integrity": "sha512-+uCOcvVmFUYvVDr27aiyun9WgZk0tXe7ThuzoUTAukZJOwS5MrGbmSlNOhx1j80GdpqbOty05XqSl5w4dQvcOA==", + "cpu": [ + "riscv64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "optional": true, + "os": [ + "linux" + ] }, - "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/@rollup/rollup-linux-x64-gnu": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.6.tgz", + "integrity": "sha512-HUNqM32dGzfBKuaDUBqFB7tP6VMN74eLZ33Q9Y1TBqRDn+qDonkAUyKWwF9BR9unV7QUzffLnz9GrnKvMqC/fw==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "optional": true, + "os": [ + "linux" + ] }, - "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/@rollup/rollup-linux-x64-musl": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.6.tgz", + "integrity": "sha512-ch7M+9Tr5R4FK40FHQk8VnML0Szi2KRujUgHXd/HjuH9ifH72GUmw6lStZBo3c3GB82vHa0ZoUfjfcM7JiiMrQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "optional": true, + "os": [ + "linux" + ] }, - "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==", + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.6.tgz", + "integrity": "sha512-VD6qnR99dhmTQ1mJhIzXsRcTBvTjbfbGGwKAHcu+52cVl15AC/kplkhxzW/uT0Xl62Y/meBKDZvoJSJN+vTeGA==", + "cpu": [ + "arm64" + ], "dev": true, - "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" - } + "optional": true, + "os": [ + "win32" + ] }, - "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==", + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.6.tgz", + "integrity": "sha512-J9AFDq/xiRI58eR2NIDfyVmTYGyIZmRcvcAoJ48oDld/NTR8wyiPUu2X/v1navJ+N/FGg68LEbX3Ejd6l8B7MQ==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "optional": true, + "os": [ + "win32" + ] }, - "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==", + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.6.tgz", + "integrity": "sha512-jqzNLhNDvIZOrt69Ce4UjGRpXJBzhUBzawMwnaDAwyHriki3XollsewxWzOzz+4yOFDkuJHtTsZFwMxhYJWmLQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.7.2.tgz", + "integrity": "sha512-RbhOOTCNoCrbfkRyoXODZp75MlpiHMgbE5MEBZAnnnLyQNgrigEj4p0lzsMDyc1zVsJDLrivB58tgg3emX0eEA==", + "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/@types/d3-force": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.9.tgz", + "integrity": "sha512-IKtvyFdb4Q0LWna6ymywQsEYjK/94SGhPrMfEr1TIc5OBeziTi+1jcCvttts8e0UWZIxpasjnQk9MNk/3iS+kA==" + }, + "node_modules/@types/d3-hierarchy": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.6.tgz", + "integrity": "sha512-qlmD/8aMk5xGorUvTUWHCiumvgaUXYldYjNVOWtYoTYY/L+WwIEAmJxUmTgr9LoGNG0PPAOmqMDJVDPc7DOpPw==" + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true }, - "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==", + "node_modules/@types/jsdom": { + "version": "21.1.6", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.6.tgz", + "integrity": "sha512-/7kkMsC+/kMs7gAYmmBR9P0vGTnOoLhQhyhQJSlXGI5bzTHp6xdo0TtKWQAsz6pmSAeVqKSbqeyP6hytqr9FDw==", "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-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" + "@types/node": "*", + "@types/tough-cookie": "*", + "parse5": "^7.0.0" } }, - "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/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.19.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.15.tgz", + "integrity": "sha512-AMZ2UWx+woHNfM11PyAEQmfSxi05jm9OlkxczuHeEqmvwPkYj6MWv44gbzDPefYOLysTOFyI3ziiy2ONmUZfpA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "undici-types": "~5.26.4" } }, - "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/@types/semver": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "dev": true + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.20.0.tgz", + "integrity": "sha512-fTwGQUnjhoYHeSF6m5pWNkzmDDdsKELYrOBxhjMrofPqCkoC2k3B2wvGHFxa1CTIqkEn88nlW1HVMztjo2K8Hg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.20.0", + "@typescript-eslint/type-utils": "6.20.0", + "@typescript-eslint/utils": "6.20.0", + "@typescript-eslint/visitor-keys": "6.20.0", + "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": ">=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" + "@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-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/@typescript-eslint/parser": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.20.0.tgz", + "integrity": "sha512-bYerPDF/H5v6V76MdMYhjwmwgMA+jlPVqjSDq2cRqMi8bP5sR3Z+RLOiOMad3nsnmDVmn2gAFCyNgh/dIrfP/w==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@typescript-eslint/scope-manager": "6.20.0", + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/typescript-estree": "6.20.0", + "@typescript-eslint/visitor-keys": "6.20.0", + "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-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/@typescript-eslint/scope-manager": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.20.0.tgz", + "integrity": "sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/visitor-keys": "6.20.0" }, "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-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/@typescript-eslint/type-utils": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.20.0.tgz", + "integrity": "sha512-qnSobiJQb1F5JjN0YDRPHruQTrX7ICsmltXhkV536mp4idGAYrIyr47zF/JmkJtEcAVnIz4gUYJ7gOZa6SmN4g==", "dev": true, "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@typescript-eslint/typescript-estree": "6.20.0", + "@typescript-eslint/utils": "6.20.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" }, "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-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==", + "node_modules/@typescript-eslint/types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.20.0.tgz", + "integrity": "sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, "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-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==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.20.0.tgz", + "integrity": "sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==", "dev": true, "dependencies": { - "@babel/helper-compilation-targets": "^7.18.6", - "@babel/helper-function-name": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/visitor-keys": "6.20.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.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-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==", + "node_modules/@typescript-eslint/utils": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.20.0.tgz", + "integrity": "sha512-/EKuw+kRu2vAqCoDwDCBtDRU6CTKbUmwwI7SH7AashZ+W+7o8eiyy6V2cdOqN49KsTcASWsC5QeghYuRDTyOOg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.20.0", + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/typescript-estree": "6.20.0", + "semver": "^7.5.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" } }, - "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==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.20.0.tgz", + "integrity": "sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@typescript-eslint/types": "6.20.0", + "eslint-visitor-keys": "^3.4.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" } }, - "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==", + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz", + "integrity": "sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==", "dev": true, - "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" + "node": "^18.0.0 || >=20.0.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "vite": "^5.0.0", + "vue": "^3.2.25" } }, - "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/@vitest/expect": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.2.2.tgz", + "integrity": "sha512-3jpcdPAD7LwHUUiT2pZTj2U82I2Tcgg2oVPvKxhn6mDI2On6tfvPQTjAI4628GUGDZrCm4Zna9iQHm5cEexOAg==", "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" + "@vitest/spy": "1.2.2", + "@vitest/utils": "1.2.2", + "chai": "^4.3.10" }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "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/@vitest/runner": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.2.2.tgz", + "integrity": "sha512-JctG7QZ4LSDXr5CsUweFgcpEvrcxOV1Gft7uHrvkQ+fsAVylmWQvnaAr/HDp3LAH1fztGMQZugIheTWjaGzYIg==", "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" + "@vitest/utils": "1.2.2", + "p-limit": "^5.0.0", + "pathe": "^1.1.1" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "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/@vitest/runner/node_modules/p-limit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "yocto-queue": "^1.0.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=18" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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/@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-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, "engines": { - "node": ">=6.9.0" + "node": ">=12.20" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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/@vitest/snapshot": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.2.2.tgz", + "integrity": "sha512-SmGY4saEw1+bwE1th6S/cZmPxz/Q4JWsl7LvbQIky2tKE35US4gd0Mjzqfr84/4OD0tikGWaWdMja/nWL5NIPA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "pretty-format": "^29.7.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "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/@vitest/spy": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.2.2.tgz", + "integrity": "sha512-k9Gcahssw8d7X3pSLq3e3XEu/0L78mUkCjivUqCQeXJm9clfXR/Td8+AP+VC1O6fKPIDLcHDTAmBOINVuv6+7g==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" + "tinyspy": "^2.2.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "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/@vitest/utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.2.2.tgz", + "integrity": "sha512-WKITBHLsBHlpjnDQahr+XK6RE7MiAsgrIkr0pGhQ9ygoxBfUeG0lUG5iLlzqjmKSlBv3+j5EGsriBzh+C3Tq9g==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" + "diff-sequences": "^29.6.3", + "estree-walker": "^3.0.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "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/@volar/language-core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-1.11.1.tgz", + "integrity": "sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@volar/source-map": "1.11.1" } }, - "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/@volar/source-map": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-1.11.1.tgz", + "integrity": "sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "regenerator-transform": "^0.15.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "muggle-string": "^0.3.1" } }, - "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/@volar/typescript": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-1.11.1.tgz", + "integrity": "sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ==", "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.11.1", + "path-browserify": "^1.0.1" } }, - "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==", - "dev": true, + "node_modules/@vue/compiler-core": { + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.15.tgz", + "integrity": "sha512-XcJQVOaxTKCnth1vCxEChteGuwG6wqnUHxAm1DO3gCz0+uXKaJNx8/digSz4dLALCy8n2lKq24jSUs8segoqIw==", "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" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/parser": "^7.23.6", + "@vue/shared": "3.4.15", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.0.2" } }, - "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==", - "dev": true, + "node_modules/@vue/compiler-core/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "node_modules/@vue/compiler-dom": { + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.15.tgz", + "integrity": "sha512-wox0aasVV74zoXyblarOM3AZQz/Z+OunYcIHe1OsGclCHt8RsRm04DObjefaI82u6XDzv+qGWZ24tIsRAIi5MQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@vue/compiler-core": "3.4.15", + "@vue/shared": "3.4.15" } }, - "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==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node_modules/@vue/compiler-sfc": { + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.15.tgz", + "integrity": "sha512-LCn5M6QpkpFsh3GQvs2mJUOAlBQcCco8D60Bcqmf3O3w5a+KWS5GvYbrrJBkgvL1BDnTp+e8q0lXCLgHhKguBA==", + "dependencies": { + "@babel/parser": "^7.23.6", + "@vue/compiler-core": "3.4.15", + "@vue/compiler-dom": "3.4.15", + "@vue/compiler-ssr": "3.4.15", + "@vue/shared": "3.4.15", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.5", + "postcss": "^8.4.33", + "source-map-js": "^1.0.2" } }, - "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==", - "dev": true, + "node_modules/@vue/compiler-sfc/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.15.tgz", + "integrity": "sha512-1jdeQyiGznr8gjFDadVmOJqZiLNSsMa5ZgqavkPZ8O2wjHv0tVuAEsw5hTdUoUW4232vpBbL/wJhzVW/JwY1Uw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@vue/compiler-dom": "3.4.15", + "@vue/shared": "3.4.15" } }, - "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/@vue/devtools-api": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.5.1.tgz", + "integrity": "sha512-+KpckaAQyfbvshdDW5xQylLni1asvNSGme1JFs8I1+/H5pHEhqUKMEQD/qn3Nx5+/nycBq11qAEi8lk+LXI2dA==" + }, + "node_modules/@vue/eslint-config-prettier": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz", + "integrity": "sha512-z1ZIAAUS9pKzo/ANEfd2sO+v2IUalz7cM/cTLOZ7vRFOPk5/xuRKQteOu1DErFLAh/lYGXMVZ0IfYKlyInuDVg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" + "eslint-config-prettier": "^9.0.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-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==", + "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-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/@vue/language-core": { + "version": "1.8.27", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.27.tgz", + "integrity": "sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" + "@volar/language-core": "~1.11.1", + "@volar/source-map": "~1.11.1", + "@vue/compiler-dom": "^3.3.0", + "@vue/shared": "^3.3.0", + "computeds": "^0.0.1", + "minimatch": "^9.0.3", + "muggle-string": "^0.3.1", + "path-browserify": "^1.0.1", + "vue-template-compiler": "^2.7.14" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "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==", - "dev": true, + "node_modules/@vue/reactivity": { + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.15.tgz", + "integrity": "sha512-55yJh2bsff20K5O84MxSvXKPHHt17I2EomHznvFiJCAZpJTNW8IuLj1xZWMLELRhBK3kkFV/1ErZGHJfah7i7w==", "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" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@vue/shared": "3.4.15" } }, - "node_modules/@babel/preset-modules": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", - "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", - "dev": true, + "node_modules/@vue/runtime-core": { + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.15.tgz", + "integrity": "sha512-6E3by5m6v1AkW0McCeAyhHTw+3y17YCOKG0U0HDKDscV4Hs0kgNT5G+GCHak16jKgcCDHpI9xe5NKb8sdLCLdw==", "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" + "@vue/reactivity": "3.4.15", + "@vue/shared": "3.4.15" } }, - "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==", - "dev": true, + "node_modules/@vue/runtime-dom": { + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.15.tgz", + "integrity": "sha512-EVW8D6vfFVq3V/yDKNPBFkZKGMFSvZrUQmx196o/v2tHKdwWdiZjYUBS+0Ez3+ohRyF8Njwy/6FH5gYJ75liUw==", "dependencies": { - "regenerator-runtime": "^0.13.4" - }, - "engines": { - "node": ">=6.9.0" + "@vue/runtime-core": "3.4.15", + "@vue/shared": "3.4.15", + "csstype": "^3.1.3" } }, - "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dev": true, + "node_modules/@vue/server-renderer": { + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.15.tgz", + "integrity": "sha512-3HYzaidu9cHjrT+qGUuDhFYvF/j643bHC6uUN9BgM11DVy+pM6ATsG6uPBLnkwOgs7BpJABReLmpL3ZPAsUaqw==", "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@vue/compiler-ssr": "3.4.15", + "@vue/shared": "3.4.15" }, - "engines": { - "node": ">=6.9.0" + "peerDependencies": { + "vue": "3.4.15" } }, - "node_modules/@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "node_modules/@vue/shared": { + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.15.tgz", + "integrity": "sha512-KzfPTxVaWfB+eGcGdbSf4CWdaXcGDqckoeXUh7SB3fZdEtzPCK2Vq9B/lRRL3yutax/LWITz+SwvgyOxz5V75g==" + }, + "node_modules/@vue/test-utils": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.4.4.tgz", + "integrity": "sha512-8jkRxz8pNhClAf4Co4ZrpAoFISdvT3nuSkUlY6Ys6rmTpw3DMWG/X3mw3gQ7QJzgCZO9f+zuE2kW57fi09MW7Q==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", - "globals": "^11.1.0" + "js-beautify": "^1.14.9", + "vue-component-type-helpers": "^1.8.21" }, - "engines": { - "node": ">=6.9.0" + "peerDependencies": { + "@vue/server-renderer": "^3.0.1", + "vue": "^3.0.1" + }, + "peerDependenciesMeta": { + "@vue/server-renderer": { + "optional": true + } } }, - "node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "node_modules/@vue/tsconfig": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@vue/tsconfig/-/tsconfig-0.5.1.tgz", + "integrity": "sha512-VcZK7MvpjuTPx2w6blwnwZAu5/LgBUtejFOi3pPGQFXQN5Ela03FUtd2Qtg4yWGGissVL0dr6Ro1LfOFh+PCuQ==", + "dev": true + }, + "node_modules/abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - }, "engines": { - "node": ">=6.9.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "node_modules/@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/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "acorn": "^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==", + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", "dev": true, "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=0.4.0" } }, - "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/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", "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" + "debug": "^4.3.4" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 14" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "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": { - "url": "https://opencollective.com/eslint" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "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/ansi-escapes": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", + "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", "dev": true, "dependencies": { - "type-fest": "^0.20.2" + "type-fest": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=14.16" }, "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/ansi-escapes/node_modules/type-fest": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", "dev": true, "engines": { - "node": ">=10" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "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/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": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=8" } }, - "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/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": { - "@hapi/hoek": "^9.0.0" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "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/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/@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/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": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" }, "engines": { - "node": ">=10.10.0" + "node": ">= 8" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } + "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/@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==", + "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/@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==", + "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": { - "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" + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, "engines": { "node": ">=8" } }, - "node_modules/@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==", + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", + "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", "dev": true, "dependencies": { - "sprintf-js": "~1.0.2" + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "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, "engines": { - "node": ">=6" + "node": "*" } }, - "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/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/autoprefixer": { + "version": "10.4.17", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.17.tgz", + "integrity": "sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==", "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": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "browserslist": "^4.22.2", + "caniuse-lite": "^1.0.30001578", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" }, "bin": { - "js-yaml": "bin/js-yaml.js" + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "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==", + "node_modules/available-typed-arrays": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz", + "integrity": "sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg==", "dev": true, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "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/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true, "engines": { "node": ">=8" } }, - "node_modules/@jest/console": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.5.0.tgz", - "integrity": "sha512-NEpkObxPwyw/XxZVLPmAGKE89IQRp4puc6IQRPru6JKd1M3fW9v1xM1AnzIJE65hbCkzQAdnL8P47e9hzhiYLQ==", + "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/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": { - "@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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "balanced-match": "^1.0.0" } }, - "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/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": { - "color-convert": "^2.0.1" + "fill-range": "^7.0.1" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@jest/console/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/browserslist": { + "version": "4.22.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", + "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", "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": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "caniuse-lite": "^1.0.30001580", + "electron-to-chromium": "^1.4.648", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" }, - "engines": { - "node": ">=10" + "bin": { + "browserslist": "cli.js" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/@jest/console/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/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": { - "color-name": "~1.1.4" - }, "engines": { - "node": ">=7.0.0" + "node": ">=8" } }, - "node_modules/@jest/console/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/call-bind": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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/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": ">=8" + "node": ">=6" } }, - "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/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": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">= 6" } }, - "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/caniuse-lite": { + "version": "1.0.30001583", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001583.tgz", + "integrity": "sha512-acWTYaha8xfhA/Du/z4sNZjHUWjkiuoAi2LM+T/aL+kemKQgPT1xBb/YKjlQ0Qo8gvbHsGNplrEJ+9G3gL7i4Q==", "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" - }, - "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 + "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/@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/chai": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", + "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "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": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=4" } }, - "node_modules/@jest/core/node_modules/chalk": { + "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -2144,216 +2024,175 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "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/@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==", - "dev": true, + "node_modules/chart.js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.1.tgz", + "integrity": "sha512-C74QN1bxwV1v2PEujhmKjOZ7iUM4w6BWs23Md/6aOZZSlwMzeCIDGuZay++rBgChYru7/+QFeoQW0fQoP534Dg==", "dependencies": { - "color-name": "~1.1.4" + "@kurkle/color": "^0.3.0" }, "engines": { - "node": ">=7.0.0" + "pnpm": ">=7" } }, - "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==", - "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==", - "dev": true, - "engines": { - "node": ">=8" + "node_modules/chartjs-chart-graph": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/chartjs-chart-graph/-/chartjs-chart-graph-4.2.8.tgz", + "integrity": "sha512-BVymOBPF5QufeAKT9pi7kJj4PYZIH492WPJ7/a7Pt6BAFv4Viuk9LgLVn7P2n1zd3O+N1F3f6fIqkp41VAzHKw==", + "dependencies": { + "@types/d3-force": "^3.0.9", + "@types/d3-hierarchy": "^3.1.6", + "d3-dispatch": "^3.0.1", + "d3-force": "^3.0.0", + "d3-hierarchy": "^3.1.2", + "d3-quadtree": "^3.0.1", + "d3-timer": "^3.0.1" + }, + "peerDependencies": { + "chart.js": "^4.1.0" } }, - "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/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/@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/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": { - "has-flag": "^4.0.0" + "get-func-name": "^2.0.2" }, "engines": { - "node": ">=8" + "node": "*" } }, - "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/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], "dependencies": { - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "jest-mock": "^29.5.0" + "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_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==", - "dev": true, - "dependencies": { - "expect": "^29.5.0", - "jest-snapshot": "^29.5.0" + "node": ">= 8.10.0" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "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/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": { - "jest-get-type": "^29.4.3" + "is-glob": "^4.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 6" } }, - "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/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": { - "@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" + "restore-cursor": "^4.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", "dev": true, "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/types": "^29.5.0", - "jest-mock": "^29.5.0" + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/cli-truncate/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": { - "@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" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "node": ">=12" }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "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/cli-truncate/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "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/cli-truncate/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-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@jest/reporters/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==", @@ -2365,2595 +2204,2147 @@ "node": ">=7.0.0" } }, - "node_modules/@jest/reporters/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/reporters/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } + "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/@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/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": { - "@types/node": "*", - "jest-util": "^29.5.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "delayed-stream": "~1.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.8" } }, - "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/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=14" } }, - "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==", - "dev": true, - "engines": { - "node": ">=8" - } + "node_modules/computeds": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz", + "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==", + "dev": true }, - "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/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/schemas": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "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": { - "@sinclair/typebox": "^0.25.16" + "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" + "node": ">= 8" } }, - "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/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": { - "@jridgewell/trace-mapping": "^0.3.15", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" + "bin": { + "cssesc": "bin/cssesc" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=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/cssstyle": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.0.1.tgz", + "integrity": "sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==", "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" + "rrweb-cssom": "^0.6.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18" } }, - "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==", - "dev": true, - "dependencies": { - "@jest/test-result": "^29.5.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "slash": "^3.0.0" - }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/@jest/test-sequencer/node_modules/slash": { + "node_modules/d3-force": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/@jest/transform": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.5.0.tgz", - "integrity": "sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw==", - "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" - }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/@jest/transform/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=12" } }, - "node_modules/@jest/transform/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=12" } }, - "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/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=18" } }, - "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==", + "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/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_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/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "ms": "2.1.2" }, "engines": { - "node": ">=8" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "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/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/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": { - "@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" + "type-detect": "^4.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6" } }, - "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/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/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">= 0.4" } }, - "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/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "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/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": { - "color-name": "~1.1.4" - }, "engines": { - "node": ">=7.0.0" + "node": ">=0.4.0" } }, - "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==", + "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/@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/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": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.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/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": { - "has-flag": "^4.0.0" + "path-type": "^4.0.0" }, "engines": { "node": ">=8" } }, - "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==", + "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": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "esutils": "^2.0.2" }, "engines": { "node": ">=6.0.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/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/@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/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": ">=6.0.0" + "node": ">=14" } }, - "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/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": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "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/electron-to-chromium": { + "version": "1.4.655", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.655.tgz", + "integrity": "sha512-2yszojF7vIZ68adIOvzV4bku8OZad9w5H9xF3ZAMZjPuOjBarlflUkjN6DggdV+L71WZuKUfKUhov/34+G5QHg==", + "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/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.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "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/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": { - "easy-stack": "1.0.1" - }, - "engines": { - "node": ">=1.0.0" + "is-arrayish": "^0.2.1" } }, - "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/es-abstract": { + "version": "1.22.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", + "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", "dev": true, "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.2", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.5", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.2", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0", + "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.12", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "safe-array-concat": "^1.0.1", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.13" }, "engines": { - "node": ">= 8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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/es-set-tostringtag": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", + "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2", + "has-tostringtag": "^1.0.0", + "hasown": "^2.0.0" + }, "engines": { - "node": ">= 8" + "node": ">= 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/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": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" }, "engines": { - "node": ">= 8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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/esbuild": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", "dev": true, - "dependencies": { - "@hapi/hoek": "^9.0.0" + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" } }, - "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==", + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true, - "dependencies": { - "type-detect": "4.0.8" + "engines": { + "node": ">=6" } }, - "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/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": { - "@sinonjs/commons": "^2.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/eslint": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", "dev": true, "dependencies": { - "chalk": "^3.0.0", - "error-stack-parser": "^2.0.6", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.56.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "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.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" }, "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" + "eslint": ">=7.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/eslint-plugin-prettier": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", + "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.6" }, "engines": { - "node": ">=8" + "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } } }, - "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/eslint-plugin-vue": { + "version": "9.21.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.21.1.tgz", + "integrity": "sha512-XVtI7z39yOVBFJyi8Ljbn7kY9yHzznKXL02qQYn+ta63Iy4A9JFBw6o4OSB9hyD2++tVT+su9kQqetUyCCwhjw==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.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.4.2", + "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/@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/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-name": "~1.1.4" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">=7.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "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==", - "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/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, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "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/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "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==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "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/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, "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/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": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "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/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "dependencies": { - "@babel/types": "^7.0.0" + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" } }, - "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/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": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" } }, - "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/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "dependencies": { - "@babel/types": "^7.3.0" + "engines": { + "node": ">=4.0" } }, - "node_modules/@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", "dev": true, "dependencies": { - "@types/connect": "*", - "@types/node": "*" + "@types/estree": "^1.0.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/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, - "dependencies": { - "@types/node": "*" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true }, - "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/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": { - "@types/express-serve-static-core": "*", - "@types/node": "*" - } - }, - "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==", - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", - "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" + "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": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "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/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/@types/express": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", - "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", - "dev": true, - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" - } + "node_modules/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/@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/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" + "@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/@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==", + "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": { - "@types/node": "*" + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" } }, - "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/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/@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/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/@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/fastq": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.0.tgz", + "integrity": "sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w==", "dev": true, "dependencies": { - "@types/istanbul-lib-coverage": "*" + "reusify": "^1.0.4" } }, - "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/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": { - "@types/istanbul-lib-report": "*" + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" } }, - "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/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": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" + "to-regex-range": "^5.0.1" + }, + "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/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": { - "@types/node": "*", - "@types/tough-cookie": "*", - "parse5": "^7.0.0" - } - }, - "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==", - "dev": true, + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, "engines": { - "node": ">=0.12" + "node": ">=10" }, "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "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/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "dependencies": { - "entities": "^4.4.0" + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "engines": { + "node": "^10.12.0 || >=12.0.0" } }, - "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==", + "node_modules/flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "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/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": { - "@types/express": "*" + "is-callable": "^1.1.3" } }, - "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/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", "dev": true, "dependencies": { - "@types/mime": "^1", - "@types/node": "*" + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@types/sockjs": { - "version": "0.3.33", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", - "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", + "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": { - "@types/node": "*" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true - }, - "node_modules/@types/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 - }, - "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/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } }, - "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==", + "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/@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==", + "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, - "dependencies": { - "@types/node": "*" + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "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/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, - "dependencies": { - "@types/yargs-parser": "*" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "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" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 0.4" }, "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 - } + "url": "https://github.com/sponsors/ljharb" } }, - "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/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, - "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" + "url": "https://github.com/sponsors/ljharb" } }, - "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/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=18" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "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/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, - "dependencies": { - "@typescript-eslint/types": "5.56.0", - "eslint-visitor-keys": "^3.3.0" - }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": "*" } }, - "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/get-intrinsic": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, - "engines": { - "node": ">=10" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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/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": { - "@typescript-eslint/scope-manager": "5.55.0", - "@typescript-eslint/types": "5.55.0", - "@typescript-eslint/typescript-estree": "5.55.0", - "debug": "^4.3.4" - }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=16" }, "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/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": { - "@typescript-eslint/types": "5.55.0", - "@typescript-eslint/visitor-keys": "5.55.0" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" }, "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/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/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.56.0", - "@typescript-eslint/utils": "5.56.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=16 || 14 >=14.17" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "url": "https://github.com/sponsors/isaacs" } }, - "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/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, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "dependencies": { + "is-glob": "^4.0.3" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "engines": { + "node": ">=10.13.0" } }, - "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/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "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" + "type-fest": "^0.20.2" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=8" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "url": "https://github.com/sponsors/sindresorhus" } }, - "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/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": { - "@typescript-eslint/types": "5.56.0", - "eslint-visitor-keys": "^3.3.0" + "define-properties": "^1.1.3" }, "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/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/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "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/@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/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": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=8" } }, - "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/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "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" + "get-intrinsic": "^1.1.3" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@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/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": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "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/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", "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" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "get-intrinsic": "^1.2.2" }, "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/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, - "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" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "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/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, "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/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/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "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" + "has-symbols": "^1.0.3" }, "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/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/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.56.0", - "eslint-visitor-keys": "^3.3.0" + "function-bind": "^1.1.2" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">= 0.4" } }, - "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/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": { - "lru-cache": "^6.0.0" - }, "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "he": "bin/he" } }, - "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==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.55.0", - "eslint-visitor-keys": "^3.3.0" - }, + "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.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=12.0.0" } }, - "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==", + "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/@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, - "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" - } - }, - "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/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", "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" + "whatwg-encoding": "^3.1.1" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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==", - "dev": true, "engines": { - "node": ">=4" - } - }, - "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": ">=18" } }, - "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/http-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", + "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", "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" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0", - "vue": "2.x" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, - "peerDependenciesMeta": { - "vue": { - "optional": true - } + "engines": { + "node": ">= 14" } }, - "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/https-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", + "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "agent-base": "^7.0.2", + "debug": "4" }, "engines": { - "node": ">=10" + "node": ">= 14" } }, - "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/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, - "dependencies": { - "@babel/plugin-syntax-jsx": "^7.2.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=16.17.0" } }, - "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/husky": { + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz", + "integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==", "dev": true, - "dependencies": { - "@babel/plugin-syntax-jsx": "^7.2.0" + "bin": { + "husky": "bin.mjs" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" } }, - "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/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": { - "@babel/plugin-syntax-jsx": "^7.2.0" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=0.10.0" } }, - "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/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, - "dependencies": { - "@babel/plugin-syntax-jsx": "^7.2.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">= 4" } }, - "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/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": { - "@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" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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==", - "dev": true, "engines": { "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "engines": { - "node": ">=4" + "node": ">=0.8.19" } }, - "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==", + "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": { - "@babel/plugin-syntax-jsx": "^7.2.0", - "@vue/babel-plugin-transform-vue-jsx": "^1.2.1", - "camelcase": "^5.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "once": "^1.3.0", + "wrappy": "1" } }, - "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/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "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/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/@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/internal-slot": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", + "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", "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" + "get-intrinsic": "^1.2.2", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" }, - "peerDependencies": { - "@vue/cli-service": "^3.0.0 || ^4.0.0 || ^5.0.0-0" + "engines": { + "node": ">= 0.4" } }, - "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/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": { - "@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" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" }, - "peerDependencies": { - "@vue/cli-service": "^3.0.0 || ^4.0.0 || ^5.0.0-0", - "eslint": ">=7.5.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "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": { - "@vue/cli-shared-utils": "^5.0.8" + "has-bigints": "^1.0.1" }, - "peerDependencies": { - "@vue/cli-service": "^3.0.0 || ^4.0.0 || ^5.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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/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": { - "@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" + "binary-extensions": "^2.0.0" }, - "peerDependenciesMeta": { - "cache-loader": { - "optional": true - }, - "vue-template-compiler": { - "optional": true - } + "engines": { + "node": ">=8" } }, - "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/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, - "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": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": "^12.0.0 || >= 14.0.0" - }, - "peerDependencies": { - "vue-template-compiler": "^2.0.0", - "webpack-sources": "*" + "node": ">= 0.4" }, - "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": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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/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": { - "minipass": "^3.1.1" - }, "engines": { - "node": ">= 8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, "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" + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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/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": { - "color-convert": "^2.0.1" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "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, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" + "node": ">=0.10.0" + } + }, + "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/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "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/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": { - "color-name": "~1.1.4" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">=7.0.0" + "node": ">=0.10.0" } }, - "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/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", "dev": true, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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/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": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, "engines": { - "node": ">=10" + "node": ">=0.12.0" } }, - "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/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=8" - } - }, - "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/@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": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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/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/@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==", - "dependencies": { - "@vue/compiler-dom": "3.2.47", - "@vue/shared": "3.2.47" - } + "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/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/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": { - "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" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, - "optionalDependencies": { - "prettier": "^1.18.2 || ^2.0.0" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@vue/component-compiler-utils/node_modules/hash-sum": { + "node_modules/is-shared-array-buffer": { "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==", + "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": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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/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": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - }, "engines": { - "node": ">=6.0.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "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=", - "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/@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/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": { - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-prettier": "^4.0.0" + "has-tostringtag": "^1.0.0" }, - "peerDependencies": { - "eslint": ">= 7.28.0", - "prettier": ">= 2.0.0" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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/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": { - "@typescript-eslint/eslint-plugin": "^5.0.0", - "@typescript-eslint/parser": "^5.0.0", - "vue-eslint-parser": "^8.0.0" + "has-symbols": "^1.0.2" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 0.4" }, - "peerDependencies": { - "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0", - "eslint-plugin-vue": "^8.0.1" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, "dependencies": { - "@vue/shared": "3.2.47" + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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/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/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" + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", - "dependencies": { - "@vue/reactivity": "3.2.47", - "@vue/shared": "3.2.47" - } + "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/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==", - "dependencies": { - "@vue/runtime-core": "3.2.47", - "@vue/shared": "3.2.47", - "csstype": "^2.6.8" - } + "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/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==", + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, "dependencies": { - "@vue/compiler-ssr": "3.2.47", - "@vue/shared": "3.2.47" + "@isaacs/cliui": "^8.0.2" }, - "peerDependencies": { - "vue": "3.2.47" + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.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/jiti": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", + "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "dev": true, + "bin": { + "jiti": "bin/jiti.js" + } }, - "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/js-beautify": { + "version": "1.14.11", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.11.tgz", + "integrity": "sha512-rPogWqAfoYh1Ryqqh2agUpVfbxAhbjuN1SmU86dskQUKouRiggUTCO4+2ym9UPXllc2WAp0J+T5qxn7Um3lCdw==", "dev": true, "dependencies": { - "js-beautify": "1.14.6" + "config-chain": "^1.1.13", + "editorconfig": "^1.0.3", + "glob": "^10.3.3", + "nopt": "^7.2.0" }, - "optionalDependencies": { - "@vue/compiler-dom": "^3.0.1", - "@vue/server-renderer": "^3.0.1" + "bin": { + "css-beautify": "js/bin/css-beautify.js", + "html-beautify": "js/bin/html-beautify.js", + "js-beautify": "js/bin/js-beautify.js" }, - "peerDependencies": { - "@vue/compiler-dom": "^3.0.1", - "@vue/server-renderer": "^3.0.1", - "vue": "^3.0.1" + "engines": { + "node": ">=14" } }, - "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/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": { - "@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" + "argparse": "^2.0.1" }, - "peerDependenciesMeta": { - "cache-loader": { - "optional": true - }, - "vue-template-compiler": { - "optional": true - } + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "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/jsdom": { + "version": "24.0.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.0.0.tgz", + "integrity": "sha512-UDS2NayCvmXSXVP6mpTj+73JnNQadZlr9N68189xib2tx5Mls7swlTNao26IoHv46BZJFvXygyRtyXd1feAk1A==", "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" + "cssstyle": "^4.0.1", + "data-urls": "^5.0.0", + "decimal.js": "^10.4.3", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.7", + "parse5": "^7.1.2", + "rrweb-cssom": "^0.6.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.3", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0", + "ws": "^8.16.0", + "xml-name-validator": "^5.0.0" }, "engines": { - "node": ">10" + "node": ">=18" }, "peerDependencies": { - "@babel/core": "7.x", - "babel-jest": "29.x", - "jest": "29.x", - "typescript": ">= 4.3", - "vue": "^3.0.0-0" + "canvas": "^2.11.2" }, "peerDependenciesMeta": { - "typescript": { + "canvas": { "optional": true } } }, - "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/jsdom/node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", "dev": true, - "dependencies": { - "mdn-data": "2.0.30", - "source-map-js": "^1.0.1" - }, "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + "node": ">=18" } }, - "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==", + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, - "node_modules/@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==", - "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==", + "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/@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_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/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "dependencies": { - "@xtuc/long": "4.2.2" - } + "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/@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/jsonc-parser": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", + "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", + "dev": true }, - "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/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", "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" + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" } }, - "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==", + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, "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" + "json-buffer": "3.0.1" } }, - "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==", + "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": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" } }, - "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/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", "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" + "immediate": "~3.0.5" } }, - "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/lilconfig": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", + "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", + "dev": true, + "engines": { + "node": ">=14" } }, - "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==", - "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/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/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" + "node_modules/lint-staged": { + "version": "15.2.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.2.tgz", + "integrity": "sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==", + "dev": true, + "dependencies": { + "chalk": "5.3.0", + "commander": "11.1.0", + "debug": "4.3.4", + "execa": "8.0.1", + "lilconfig": "3.0.0", + "listr2": "8.0.1", + "micromatch": "4.0.5", + "pidtree": "0.6.0", + "string-argv": "0.3.2", + "yaml": "2.3.4" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" }, "engines": { - "node": ">=6.5" + "node": ">=18.12.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" } }, - "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/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": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, "engines": { - "node": ">= 0.6" + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "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" - }, + "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": ">=0.4.0" + "node": ">=16" } }, - "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/listr2": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.0.1.tgz", + "integrity": "sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==", "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" + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.0.0", + "rfdc": "^1.3.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18.0.0" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "node_modules/listr2/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, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "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/listr2/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": ">=0.4.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/address": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz", - "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==", + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/listr2/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, "engines": { - "node": ">= 0.12.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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/listr2/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": { - "debug": "4" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">= 6.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "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/listr2/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "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": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "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/local-pkg": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", + "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", "dev": true, "dependencies": { - "ajv": "^8.0.0" + "mlly": "^1.4.2", + "pkg-types": "^1.0.3" }, - "peerDependencies": { - "ajv": "^8.0.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/antfu" } }, - "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/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": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "url": "https://github.com/sponsors/sindresorhus" } }, - "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/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "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/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/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/log-update": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", + "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", "dev": true, "dependencies": { - "type-fest": "^0.21.3" + "ansi-escapes": "^6.2.0", + "cli-cursor": "^4.0.0", + "slice-ansi": "^7.0.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true, - "engines": [ - "node >= 0.8.0" - ], - "bin": { - "ansi-html": "bin/ansi-html" - } - }, - "node_modules/ansi-regex": { + "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==", @@ -4965,1422 +4356,1285 @@ "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "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/log-update/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, - "dependencies": { - "color-convert": "^1.9.0" - }, "engines": { - "node": ">=4" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", + "node_modules/log-update/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", "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/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", "dev": true, "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "get-east-asian-width": "^1.0.0" }, "engines": { - "node": ">= 8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", - "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, - "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_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": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/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/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", "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" + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" }, "engines": { - "node": "^10 || ^12 || >=14" + "node": ">=18" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.1.0" + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "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==", + "node_modules/log-update/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "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/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": { - "@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" + "ansi-regex": "^6.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" }, - "peerDependencies": { - "@babel/core": "^7.8.0" + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "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/log-update/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/babel-jest/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", "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" + "get-func-name": "^2.0.1" } }, - "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/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/magic-string": { + "version": "0.30.6", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.6.tgz", + "integrity": "sha512-n62qCLbPjNjyo+owKtveQxZFZTBm+Ms6YoGD23Wew6Vw337PElFNifQpknPruVRQV57kVShPnLGo9vWxVhpPvA==", "dependencies": { - "color-name": "~1.1.4" + "@jridgewell/sourcemap-codec": "^1.4.15" }, "engines": { - "node": ">=7.0.0" + "node": ">=12" } }, - "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==", - "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/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": ">=8" + "node": ">= 0.10.0" } }, - "node_modules/babel-jest/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, "engines": { - "node": ">=8" + "node": ">= 8" } }, - "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/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": { - "has-flag": "^4.0.0" + "braces": "^3.0.2", + "picomatch": "^2.3.1" }, "engines": { - "node": ">=8" + "node": ">=8.6" } }, - "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/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": { - "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.6" } }, - "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/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": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" + "mime-db": "1.52.0" }, "engines": { - "node": ">=8.9.0" + "node": ">= 0.6" } }, - "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/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, - "dependencies": { - "object.assign": "^4.1.0" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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/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-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" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "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/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", "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" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=16 || 14 >=14.17" } }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz", - "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.13.11", - "@babel/helper-define-polyfill-provider": "^0.3.1", - "semver": "^6.1.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "node_modules/mitt": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-2.1.0.tgz", + "integrity": "sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg==" }, - "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/mlly": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.5.0.tgz", + "integrity": "sha512-NPVQvAY1xr1QoVeG0cy8yUYC7FQcOx6evl/RjT1wL5FvzPnzOysoqB/jmx/DhssT2dYa8nxECLAaFI/+gVLhDQ==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.1", - "core-js-compat": "^3.21.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "acorn": "^8.11.3", + "pathe": "^1.1.2", + "pkg-types": "^1.0.3", + "ufo": "^1.3.2" } }, - "node_modules/babel-plugin-polyfill-regenerator": { + "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/muggle-string": { "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==", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.3.1.tgz", + "integrity": "sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==", + "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": { - "@babel/helper-define-polyfill-provider": "^0.3.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.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" + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "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/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/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "node_modules/nopt": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", + "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==", "dev": true, "dependencies": { - "babel-plugin-jest-hoist": "^29.5.0", - "babel-preset-current-node-syntax": "^1.0.0" + "abbrev": "^2.0.0" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "bin": { + "nopt": "bin/nopt.js" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "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/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/batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", - "dev": true + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } }, - "node_modules/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/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": "*" + "node": ">=0.10.0" } }, - "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/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": ">=8" + "node": ">=0.10.0" } }, - "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/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": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" + "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": ">= 4" } }, - "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/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": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "color-convert": "^1.9.0" }, "engines": { - "node": ">= 6" + "node": ">=4" } }, - "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/npm-run-all/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": { - "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" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "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/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": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, "engines": { - "node": ">= 0.8" + "node": ">=4" } }, - "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/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": { - "ms": "2.0.0" + "color-name": "1.1.3" } }, - "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/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/bonjour": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", - "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "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": { - "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" + "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/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true + "node_modules/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" + } }, - "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/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, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "engines": { + "node": ">=4" } }, - "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/npm-run-all/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": { - "fill-range": "^7.0.1" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=8" + "node": "*" } }, - "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/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, + "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==", - "dependencies": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" + "node_modules/npm-run-all/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, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" } }, - "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/npm-run-all/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" } }, - "node_modules/browserify-rsa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", - "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "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, "dependencies": { - "bn.js": "^5.0.0", - "randombytes": "^2.0.1" + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/browserify-sign": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.2.tgz", - "integrity": "sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg==", - "dependencies": { - "bn.js": "^5.2.1", - "browserify-rsa": "^4.1.0", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.4", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.6", - "readable-stream": "^3.6.2", - "safe-buffer": "^5.2.1" - }, + "node_modules/npm-run-all/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, "engines": { - "node": ">= 4" + "node": ">=0.10.0" } }, - "node_modules/browserify-sign/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "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": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "has-flag": "^3.0.0" }, "engines": { - "node": ">= 6" + "node": ">=4" } }, - "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==", + "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": { - "pako": "~1.0.5" + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" } }, - "node_modules/browserslist": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.1.tgz", - "integrity": "sha512-Nq8MFCSrnJXSc88yliwlzQe3qNe3VntIjhsArW9IJOEPSHNx23FalwApUVbzAWABLhYJJ7y8AynWI/XM8OdfjQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], + "node_modules/npm-run-path": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.2.0.tgz", + "integrity": "sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==", + "dev": true, "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" + "path-key": "^4.0.0" }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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/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": { - "fast-json-stable-stringify": "2.x" - }, "engines": { - "node": ">= 6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/bser": { + "node_modules/nth-check": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "dev": true, "dependencies": { - "node-int64": "^0.4.0" + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "node_modules/nwsapi": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", + "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", + "dev": true + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "node_modules/buffer-indexof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", - "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", - "dev": true - }, - "node_modules/buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==" - }, - "node_modules/builtin-status-codes": { + "node_modules/object-hash": { "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/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", "dev": true, "engines": { - "node": ">= 0.8" + "node": ">= 6" } }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, "engines": { - "node": ">=6" + "node": ">= 0.4" } }, - "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/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, - "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==", - "dev": true, + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "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/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": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" + "wrappy": "1" } }, - "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==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - } - ] - }, - "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/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": ">=4" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" }, "engines": { - "node": ">=4" + "node": ">= 0.8.0" } }, - "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/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/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/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "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, - "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" + "p-limit": "^3.0.2" }, "engines": { - "node": ">= 8.10.0" + "node": ">=10" }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "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": { - "is-glob": "^4.0.1" + "callsites": "^3.0.0" }, "engines": { - "node": ">= 6" + "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==", + "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": ">=6.0" + "node": ">=4" } }, - "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==", + "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": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/cjs-module-lexer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", "dev": true }, - "node_modules/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/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": { - "source-map": "~0.6.0" - }, "engines": { - "node": ">= 10.0" + "node": ">=8" } }, - "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/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "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/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, - "dependencies": { - "restore-cursor": "^3.1.0" - }, "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==", + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", "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" + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=8.0.0", - "npm": ">=5.0.0" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "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/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": { - "color-convert": "^2.0.1" - }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "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/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true + }, + "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": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": "*" } }, - "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==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.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==", - "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/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, - "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==", + "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": "*" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "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/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", "dev": true, - "dependencies": { - "has-flag": "^4.0.0" + "bin": { + "pidtree": "bin/pidtree.js" }, "engines": { - "node": ">=8" + "node": ">=0.10" } }, - "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/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": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "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, + "node_modules/pinia": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.1.7.tgz", + "integrity": "sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==", "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "@vue/devtools-api": "^6.5.0", + "vue-demi": ">=0.14.5" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "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==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "url": "https://github.com/sponsors/posva" }, - "engines": { - "node": ">=12" + "peerDependencies": { + "@vue/composition-api": "^1.4.0", + "typescript": ">=4.4.4", + "vue": "^2.6.14 || ^3.3.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + }, + "typescript": { + "optional": true + } } }, - "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==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" + "node_modules/pinia/node_modules/vue-demi": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz", + "integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==", + "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/chalk/strip-ansi?sponsor=1" + "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/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/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", "dev": true, - "dependencies": { - "arch": "^2.1.1", - "execa": "^1.0.0", - "is-wsl": "^2.1.1" - }, "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "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": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true, - "engines": { - "node": ">=0.8" + "jsonc-parser": "^3.2.0", + "mlly": "^1.2.0", + "pathe": "^1.1.0" } }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "node_modules/playwright": { + "version": "1.41.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.2.tgz", + "integrity": "sha512-v0bOa6H2GJChDL8pAeLa/LZC4feoAMbSQm1/jF/ySsWWoaNItvrMP7GEkvEEFyCTUYKMxjQKaTSg5up7nR6/8A==", "dev": true, "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" + "playwright-core": "1.41.2" + }, + "bin": { + "playwright": "cli.js" }, "engines": { - "node": ">=6" + "node": ">=16" + }, + "optionalDependencies": { + "fsevents": "2.3.2" } }, - "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/playwright-core": { + "version": "1.41.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.2.tgz", + "integrity": "sha512-VaTvwCA4Y8kxEe+kfm2+uUUw5Lubf38RxF7FpBxLPmGe5sdNkSg5e3ChEigaGrX7qdqT3pt2m/98LiyvU2x6CA==", "dev": true, + "bin": { + "playwright-core": "cli.js" + }, "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" + "node": ">=16" } }, - "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, + "node_modules/postcss": { + "version": "8.4.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", + "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "color-name": "1.1.3" + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" } }, - "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==", + "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": { - "delayed-stream": "~1.0.0" + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" }, "engines": { - "node": ">= 0.8" + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" } }, - "node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "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": { + "camelcase-css": "^2.0.1" + }, "engines": { - "node": ">= 12" + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" } }, - "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==", + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "mime-db": ">= 1.43.0 < 2" + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" }, "engines": { - "node": ">= 0.6" + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } } }, - "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "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": { - "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" + "postcss-selector-parser": "^6.0.11" }, "engines": { - "node": ">= 0.8.0" + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" } }, - "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==", + "node_modules/postcss-selector-parser": { + "version": "6.0.15", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz", + "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==", "dev": true, "dependencies": { - "ms": "2.0.0" + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" } }, - "node_modules/compression/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "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/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==", + "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" + "node": ">= 0.8.0" } }, - "node_modules/console-browserify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", - "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" - }, - "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==", + "node_modules/prettier": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", "dev": true, - "dependencies": { - "bluebird": "^3.1.1" + "bin": { + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">= 0.10.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/constants-browserify": { + "node_modules/prettier-linter-helpers": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==" + "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/prettier-plugin-tailwindcss": { + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.5.11.tgz", + "integrity": "sha512-AvI/DNyMctyyxGOjyePgi/gqj5hJYClZ1avtQvLlqMT3uDZkRbi4HhGUpok3DRzv9z7Lti85Kdj3s3/1CeNI0w==", + "dev": true, + "engines": { + "node": ">=14.21.3" + }, + "peerDependencies": { + "@ianvs/prettier-plugin-sort-imports": "*", + "@prettier/plugin-pug": "*", + "@shopify/prettier-plugin-liquid": "*", + "@trivago/prettier-plugin-sort-imports": "*", + "prettier": "^3.0", + "prettier-plugin-astro": "*", + "prettier-plugin-css-order": "*", + "prettier-plugin-import-sort": "*", + "prettier-plugin-jsdoc": "*", + "prettier-plugin-marko": "*", + "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 + }, + "@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/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==", + "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": { - "safe-buffer": "5.2.1" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">= 0.6" + "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-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.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=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==", + "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": [ { @@ -6397,1305 +5651,1113 @@ } ] }, - "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/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/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==", + "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": { - "safe-buffer": "~5.1.1" + "pify": "^2.3.0" } }, - "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==", + "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": ">= 0.6" + "node": ">=0.10.0" } }, - "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==", + "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": { - "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" + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" }, "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" + "node": ">=4" } }, - "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==", + "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": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" + "pify": "^3.0.0" }, "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=4" } }, - "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/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/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==", + "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": { - "browserslist": "^4.21.1", - "semver": "7.0.0" + "picomatch": "^2.2.1" }, - "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" + "engines": { + "node": ">=8.10.0" } }, - "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==", + "node_modules/regexp.prototype.flags": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", "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" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "set-function-name": "^2.0.0" }, "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": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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/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/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "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" + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" }, - "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" + "resolve": "bin/resolve" }, - "engines": { - "node": "*" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "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, - "dependencies": { - "timsort": "^0.3.0" - }, "engines": { - "node": ">= 10" - }, - "peerDependencies": { - "postcss": "^8.0.9" + "node": ">=4" } }, - "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==", + "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": { - "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" + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" }, "engines": { - "node": ">= 12.13.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "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": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, "engines": { - "node": ">=10" + "node": ">=6" } }, - "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==", + "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": { - "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" + "mimic-fn": "^2.1.0" }, "engines": { - "node": ">= 12.13.0" + "node": ">=6" }, "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 - } + "url": "https://github.com/sponsors/sindresorhus" } }, - "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/restore-cursor/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/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==", + "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": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, - "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==", + "node_modules/rfdc": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", "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==", + "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": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" + "glob": "^7.1.3" }, - "engines": { - "node": ">= 12.13.0" + "bin": { + "rimraf": "bin.js" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://github.com/sponsors/isaacs" } }, - "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==", + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "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" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "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==", + "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": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" + "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": ">=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" + "node": "*" }, "funding": { - "url": "https://github.com/sponsors/fb55" + "url": "https://github.com/sponsors/isaacs" } }, - "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==", + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "bin": { - "cssesc": "bin/cssesc" + "dependencies": { + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=4" + "node": "*" } }, - "node_modules/cssnano": { - "version": "5.0.17", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.0.17.tgz", - "integrity": "sha512-fmjLP7k8kL18xSspeXTzRhaFtRI7DL9b8IcXR80JgtnWBpvAzHT7sCR/6qdn0tnxIaINUN6OEQu83wF57Gs3Xw==", + "node_modules/rollup": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.6.tgz", + "integrity": "sha512-05lzkCS2uASX0CiLFybYfVkwNbKZG5NFQ6Go0VWyogFTXXbR039UVsegViTntkk4OglHBdF54ccApXRRuXRbsg==", "dev": true, "dependencies": { - "cssnano-preset-default": "^5.1.12", - "lilconfig": "^2.0.3", - "yaml": "^1.10.2" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" + "@types/estree": "1.0.5" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/cssnano" + "bin": { + "rollup": "dist/bin/rollup" }, - "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" + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" }, - "peerDependencies": { - "postcss": "^8.2.15" + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.9.6", + "@rollup/rollup-android-arm64": "4.9.6", + "@rollup/rollup-darwin-arm64": "4.9.6", + "@rollup/rollup-darwin-x64": "4.9.6", + "@rollup/rollup-linux-arm-gnueabihf": "4.9.6", + "@rollup/rollup-linux-arm64-gnu": "4.9.6", + "@rollup/rollup-linux-arm64-musl": "4.9.6", + "@rollup/rollup-linux-riscv64-gnu": "4.9.6", + "@rollup/rollup-linux-x64-gnu": "4.9.6", + "@rollup/rollup-linux-x64-musl": "4.9.6", + "@rollup/rollup-win32-arm64-msvc": "4.9.6", + "@rollup/rollup-win32-ia32-msvc": "4.9.6", + "@rollup/rollup-win32-x64-msvc": "4.9.6", + "fsevents": "~2.3.2" } }, - "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==", + "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/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, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "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/csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "node_modules/safe-array-concat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", + "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", "dev": true, "dependencies": { - "css-tree": "^1.1.2" + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" }, "engines": { - "node": ">=8.0.0" + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/cssom": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", - "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true }, - "node_modules/cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safe-regex-test": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.2.tgz", + "integrity": "sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==", "dev": true, "dependencies": { - "cssom": "~0.3.6" + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", + "is-regex": "^1.1.4" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/cssstyle/node_modules/cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, - "node_modules/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==", + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", "dev": true, "dependencies": { - "abab": "^2.0.6", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^11.0.0" + "xmlchars": "^2.2.0" }, "engines": { - "node": ">=12" + "node": ">=v12.22.7" } }, - "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==", + "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, "dependencies": { - "punycode": "^2.1.1" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=12" + "node": ">=10" } }, - "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==", + "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, + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { - "node": ">=12" + "node": ">=10" } }, - "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==", + "node_modules/set-function-length": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz", + "integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==", "dev": true, "dependencies": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" + "define-data-property": "^1.1.1", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.2", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.1" }, "engines": { - "node": ">=12" + "node": ">= 0.4" } }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "node_modules/set-function-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", "dev": true, "dependencies": { - "ms": "2.1.2" + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">= 0.4" } }, - "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/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" }, - "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==", + "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": { - "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" + "shebang-regex": "^3.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=8" } }, - "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==", + "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": ">=0.10.0" + "node": ">=8" } }, - "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==", + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", "dev": true, - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">= 10" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", "dev": true, "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" }, - "engines": { - "node": ">= 8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "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 + }, + "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, - "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" + "node": ">=14" }, "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "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, + "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": ">=10" + "node": ">=14.16" }, "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==", + "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": ">=8" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "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==", + "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, - "dependencies": { - "path-key": "^3.0.0" - }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "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, + "node_modules/sortablejs": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.2.tgz", + "integrity": "sha512-FJF5jgdfvoKn1MAKSdGs33bIqLi3LmsgVTliuX6iITj834F+JRQZN90Z93yql8h0K2t0RwDPBmxwlbZfDcxNZA==", + "peer": true + }, + "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": ">=8" + "node": ">=0.10.0" } }, - "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==", + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, - "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/spdx-exceptions": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.4.0.tgz", + "integrity": "sha512-hcjppoJ68fhxA/cjbN4T8N6uCUejN8yFw69ttpqtBeCbF3u13n7mb31NB9jKwGTTWWnt9IbRA/mf1FprYS8wfw==", + "dev": true }, - "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==", + "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": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, - "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, + "node_modules/spdx-license-ids": { + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", + "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", + "dev": true + }, + "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 + }, + "node_modules/std-env": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", + "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", + "dev": true + }, + "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": { - "clone": "^1.0.2" + "safe-buffer": "~5.1.0" } }, - "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==", + "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": ">=8" + "node": ">=0.6.19" } }, - "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==", + "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": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/del": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", - "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "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" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/del/node_modules/slash": { + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "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/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "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": ">=0.4.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "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, - "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, + "ansi-regex": "^6.0.1" + }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "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==", + "node_modules/string.prototype.padend": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.5.tgz", + "integrity": "sha512-DOB27b/2UTTD+4myKUFh+/fXWcu/UDyASIXfg+7VzoCNNGOfWvoyU/x5pvVHr++ztyt/oSYI1BcWBBG/hmlNjA==", "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/string.prototype.trim": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "dev": true, "dependencies": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/string.prototype.trimend": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", "dev": true, "dependencies": { - "path-type": "^4.0.0" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/string.prototype.trimstart": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", "dev": true, "dependencies": { - "ip": "^1.1.0", - "safe-buffer": "^5.0.1" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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=", + "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": { - "buffer-indexof": "^1.0.0" + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "dependencies": { - "esutils": "^2.0.2" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=6.0.0" + "node": ">=8" } }, - "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==", + "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, - "dependencies": { - "utila": "~0.4" + "engines": { + "node": ">=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==", + "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, - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" + "engines": { + "node": ">=12" }, "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "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": ">=10" + "node": ">=8" }, "funding": { - "url": "https://bevry.me/fund" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "node_modules/strip-literal": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.3.0.tgz", + "integrity": "sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] + "dependencies": { + "acorn": "^8.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } }, - "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==", + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", "dev": true, "dependencies": { - "webidl-conversions": "^7.0.0" + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "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": ">=12" + "node": ">=16 || 14 >=14.17" } }, - "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==", + "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": ">=12" + "node": ">= 6" } }, - "node_modules/domhandler": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz", - "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==", + "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": { - "domelementtype": "^2.2.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 4" + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "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/synckit": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", "dev": true, "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" + "url": "https://opencollective.com/unts" } }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "node_modules/tailwindcss": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz", + "integrity": "sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==", "dev": true, "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" + "@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.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.19.1", + "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" } }, - "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==", + "node_modules/tailwindcss/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/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": { + "node_modules/text-table": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "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==", + "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, - "engines": { - "node": ">=6.0.0" + "dependencies": { + "any-promise": "^1.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==", + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", "dev": true, "dependencies": { - "commander": "^2.19.0", - "lru-cache": "^4.1.5", - "semver": "^5.6.0", - "sigmund": "^1.0.1" + "thenify": ">= 3.1.0 < 4" }, - "bin": { - "editorconfig": "bin/editorconfig" + "engines": { + "node": ">=0.8" } }, - "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==", + "node_modules/tinybench": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.6.0.tgz", + "integrity": "sha512-N8hW3PG/3aOoZAN5V/NSAEDz0ZixDSSt5b/a05iqtpgfLWMSVuCo7w0k2vVvEjdrIoeGqZzweX2WlyioNIHchA==", "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==", + "node_modules/tinypool": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.2.tgz", + "integrity": "sha512-SUszKYe5wgsxnNOVlBYO6IC+8VGWdVGZWAqUxp3UErNBtptZvWbwyUOyzNL59zigz2rCA92QiL3wvG+JDSdJdQ==", "dev": true, - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "engines": { + "node": ">=14.0.0" } }, - "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==", + "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, - "bin": { - "semver": "bin/semver" + "engines": { + "node": ">=14.0.0" } }, - "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==", + "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": { - "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" + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" } }, - "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==", + "node_modules/tough-cookie": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", + "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", "dev": true, - "engines": { - "node": ">=12" + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" + "engines": { + "node": ">=6" } }, - "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==", + "node_modules/tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", "dev": true, + "dependencies": { + "punycode": "^2.3.1" + }, "engines": { - "node": ">= 4" + "node": ">=18" } }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "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, "engines": { - "node": ">= 0.8" + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.0" } }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } + "node_modules/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 + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true }, - "node_modules/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==", + "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": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "prelude-ls": "^1.2.1" }, "engines": { - "node": ">=10.13.0" + "node": ">= 0.8.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==", + "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": ">=6" + "node": ">=4" } }, - "node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "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/fb55/entities?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", "dev": true, "dependencies": { - "is-arrayish": "^0.2.1" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" } }, - "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==", + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", "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" + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" }, "engines": { "node": ">= 0.4" @@ -7704,19 +6766,17 @@ "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==", + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dev": true, "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" }, "engines": { "node": ">= 0.4" @@ -7725,24684 +6785,728 @@ "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/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" + } }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "devOptional": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, "engines": { - "node": ">=6" + "node": ">=14.17" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "node_modules/ufo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.2.tgz", + "integrity": "sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==", "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==", + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, "dependencies": { - "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" + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" }, - "optionalDependencies": { - "source-map": "~0.6.1" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/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" + "node": ">= 4.0.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==", + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", "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": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "escalade": "^3.1.1", + "picocolors": "^1.0.0" }, - "engines": { - "node": ">= 0.8.0" + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.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==", + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "dependencies": { - "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" + "punycode": "^2.1.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==", + "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, - "engines": { - "node": ">= 0.8.0" + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.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==", + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "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": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.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==", + "node_modules/vite": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.1.tgz", + "integrity": "sha512-wclpAgY3F1tR7t9LL5CcHC41YPkQIpKUGeIuT8MdNwNZr6OqOTLs7JX5vIHAtzqLWXts0T+GDrh9pN2arneKqg==", "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" + "esbuild": "^0.19.3", + "postcss": "^8.4.35", + "rollup": "^4.2.0" }, "bin": { - "eslint": "bin/eslint.js" + "vite": "bin/vite.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.0.0 || >=20.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" + "url": "https://github.com/vitejs/vite?sponsor=1" }, - "engines": { - "node": ">=12.0.0" + "optionalDependencies": { + "fsevents": "~2.3.3" }, "peerDependencies": { - "eslint": ">=7.28.0", - "prettier": ">=2.0.0" + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" }, "peerDependenciesMeta": { - "eslint-config-prettier": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { "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==", + "node_modules/vite-node": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.2.2.tgz", + "integrity": "sha512-1as4rDTgVWJO3n1uHmUYqq7nsFgINQ9u+mRcXpjeOMJUmviqNKjcZB7UfRZrlM7MjYXMKpuWp5oGkjaFLnjawg==", "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" + "cac": "^6.7.14", + "debug": "^4.3.4", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.0.0 || >=20.0.0" }, - "peerDependencies": { - "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "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==", + "node_modules/vite/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/vitest": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.2.2.tgz", + "integrity": "sha512-d5Ouvrnms3GD9USIK36KG8OZ5bEvKEkITFtnGv56HFaSlbItJuYr7hv2Lkn903+AvRAgSixiamozUVfORUekjw==", + "dev": true, + "dependencies": { + "@vitest/expect": "1.2.2", + "@vitest/runner": "1.2.2", + "@vitest/snapshot": "1.2.2", + "@vitest/spy": "1.2.2", + "@vitest/utils": "1.2.2", + "acorn-walk": "^8.3.2", + "cac": "^6.7.14", + "chai": "^4.3.10", + "debug": "^4.3.4", + "execa": "^8.0.1", + "local-pkg": "^0.5.0", + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "std-env": "^3.5.0", + "strip-literal": "^1.3.0", + "tinybench": "^2.5.1", + "tinypool": "^0.8.2", + "vite": "^5.0.0", + "vite-node": "1.2.2", + "why-is-node-running": "^2.2.2" }, "bin": { - "semver": "bin/semver.js" + "vitest": "vitest.mjs" }, "engines": { - "node": ">=10" + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "^1.0.0", + "@vitest/ui": "^1.0.0", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } } }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "node_modules/vue": { + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.15.tgz", + "integrity": "sha512-jC0GH4KkWLWJOEQjOpkqU1bQsBwf4R1rsFtw5GQJbjHVKWDzO6P0nWWBTmjp1xSemAioDFj1jdaK1qa3DnMQoQ==", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "@vue/compiler-dom": "3.4.15", + "@vue/compiler-sfc": "3.4.15", + "@vue/runtime-dom": "3.4.15", + "@vue/server-renderer": "3.4.15", + "@vue/shared": "3.4.15" }, - "engines": { - "node": ">=8.0.0" + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "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==", + "node_modules/vue-chartjs": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/vue-chartjs/-/vue-chartjs-5.3.0.tgz", + "integrity": "sha512-8XqX0JU8vFZ+WA2/knz4z3ThClduni2Nm0BMe2u0mXgTfd9pXrmJ07QBI+WAij5P/aPmPMX54HCE1seWL37ZdQ==", + "peerDependencies": { + "chart.js": "^4.1.1", + "vue": "^3.0.0-0 || ^2.7.0" + } + }, + "node_modules/vue-component-type-helpers": { + "version": "1.8.27", + "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-1.8.27.tgz", + "integrity": "sha512-0vOfAtI67UjeO1G6UiX5Kd76CqaQ67wrRZiOe7UAb9Jm6GzlUr/fC7CV90XfwapJRjpCMaZFhv1V0ajWRmE9Dg==", + "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.4.2", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.2.tgz", + "integrity": "sha512-Ry9oiGmCAK91HrKMtCrKFWmSFWvYkpGglCeFAIqDdr9zdXmMMpJOmUJS7WWsW7fX81h6mwHmUZCQQ1E0PkSwYQ==", "dev": true, "dependencies": { - "eslint-visitor-keys": "^2.0.0" + "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": "^10.0.0 || ^12.0.0 || >= 14.0.0" + "node": "^14.17.0 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/mysticatea" }, "peerDependencies": { - "eslint": ">=5" + "eslint": ">=6.0.0" } }, - "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/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/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/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/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, + "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": { - "@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" + "@vue/devtools-api": "^6.5.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://github.com/sponsors/posva" }, "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.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", - "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", - "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.4", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", - "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", - "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.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", - "dev": true, - "requires": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" - } - }, - "@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.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", - "dev": true, - "requires": { - "@babel/types": "^7.23.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "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.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "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.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "requires": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@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.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", - "dev": true - }, - "@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "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.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==" - }, - "@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.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" - } - }, - "@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "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.2", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.2.tgz", - "integrity": "sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg==", - "requires": { - "bn.js": "^5.2.1", - "browserify-rsa": "^4.1.0", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.4", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.6", - "readable-stream": "^3.6.2", - "safe-buffer": "^5.2.1" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "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 - } - } - }, - "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": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "saxes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", - "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "dev": true, - "requires": { - "xmlchars": "^2.2.0" - } - }, - "schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - } - }, - "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==", - "dev": true, - "requires": { - "node-forge": "^1.2.0" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "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": { - "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 - }, - "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" - } - }, - "shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "shell-quote": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", - "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", - "dev": true - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha512-fCvEXfh6NWpm+YSuY2bpXb/VIihqWA6hLsgboC+0nl71Q7N7o2eaCW8mJa/NLvQhs6jpd3VZV4UiUQlV6+lc8g==", - "dev": true - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "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" - } - }, - "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": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dev": true, - "requires": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "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 - } - } - }, - "sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", - "dev": true, - "requires": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" - } - }, - "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": { - "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" - } - }, - "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==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", - "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", - "dev": true - }, - "spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - } - }, - "spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "dev": true - }, - "stack-utils": { - "version": "2.0.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" - }, - "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 - } - } - }, - "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" - } - } - } - }, - "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" - } - } - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "string-argv": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", - "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", - "dev": true - }, - "string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "requires": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "string.prototype.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": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - } - }, - "string.prototype.trimstart": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", - "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "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 - } - } - }, - "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 - }, - "strip-indent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", - "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "stylehacks": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.0.3.tgz", - "integrity": "sha512-ENcUdpf4yO0E1rubu8rkxI+JGQk4CgjchynZ4bDBJDfqdy+uhTRSWb8/F3Jtu+Bw5MW45Po3/aQGeIyyxgQtxg==", - "dev": true, - "requires": { - "browserslist": "^4.16.6", - "postcss-selector-parser": "^6.0.4" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "supports-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" - }, - "dependencies": { - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - } - } - }, - "symbol-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==" - } - } - }, - "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" - } - } - } - }, - "test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, - "requires": { - "any-promise": "^1.0.0" - } - }, - "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, - "requires": { - "thenify": ">= 3.1.0 < 4" - } - }, - "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==", - "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" - } - }, - "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 - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "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": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", - "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", - "dev": true, - "requires": { - "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 - } - } - }, - "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, - "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" - } - } - } - }, - "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, - "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" - }, - "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 - } - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "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": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "type-fest": { - "version": "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 - }, - "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" - } - }, - "typescript": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz", - "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==", - "dev": true - }, - "unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "requires": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - } - }, - "unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "dev": true - }, - "unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, - "requires": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - } - }, - "unicode-match-property-value-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", - "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", - "dev": true - }, - "unicode-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 - }, - "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": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - } - }, - "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" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" - } - } - }, - "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": { - "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": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", - "dev": true - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true - }, - "v8-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": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "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==", - "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" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "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" - } - } - } - }, - "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 - }, - "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" - } - }, - "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 - }, - "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" - } - }, - "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-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": {} - }, - "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": {} - }, - "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" - } - }, - "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, - "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 - } - } - }, - "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 - }, - "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": { - "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" - } - }, - "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": { - "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" - } - } + "vue": "^3.2.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==", + "node_modules/vue-template-compiler": { + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz", + "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==", "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 - } + "de-indent": "^1.0.2", + "he": "^1.2.0" } }, - "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" - } - } + "node_modules/vue-tsc": { + "version": "1.8.27", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.27.tgz", + "integrity": "sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==", + "dev": true, + "dependencies": { + "@volar/typescript": "~1.11.1", + "@vue/language-core": "1.8.27", + "semver": "^7.5.4" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": "*" } }, - "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": {} - } + "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" } }, - "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==", + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", "dev": true, - "requires": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" } }, - "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/w3c-xmlserializer/node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", "dev": true, - "requires": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" + "engines": { + "node": ">=18" } }, - "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 + "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" + } }, - "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==", + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", "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": ">=18" } }, - "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": { - "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 + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "engines": { + "node": ">=18" + } }, - "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": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", "dev": true, - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "dependencies": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" } }, - "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": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.20.0", + "node_modules/which-typed-array": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", + "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.6", + "call-bind": "^1.0.5", "for-each": "^0.3.3", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.1" + }, + "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.4", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", - "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", - "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": { + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, - "requires": { + "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-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "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 - } + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "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.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", "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": { + "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 }, - "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.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", "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..b1d1d8a06 100644 --- a/report-viewer/package.json +++ b/report-viewer/package.json @@ -1,64 +1,66 @@ { "name": "report-viewer", - "version": "0.1.0", + "version": "0.0.0", "private": true, + "type": "module", "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", + "build-demo": "run-p type-check && vite build --mode demo", + "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 --max-warnings 0", + "format": "prettier --write src/", + "prepare": "cd .. && husky report-viewer/.husky" }, "dependencies": { - "@highlightjs/vue-plugin": "^2.1.0", - "chart.js": "^3.9.1", + "@fortawesome/fontawesome-svg-core": "^6.5.1", + "@fortawesome/free-brands-svg-icons": "^6.5.1", + "@fortawesome/free-regular-svg-icons": "^6.5.1", + "@fortawesome/free-solid-svg-icons": "^6.5.1", + "@fortawesome/vue-fontawesome": "^3.0.5", + "chart.js": "^4.4.1", + "chartjs-chart-graph": "^4.2.8", "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.3.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.40.1", + "@rushstack/eslint-patch": "^1.7.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^18.19.15", + "@vitejs/plugin-vue": "^5.0.4", + "@vue/eslint-config-prettier": "^9.0.0", + "@vue/eslint-config-typescript": "^12.0.0", + "@vue/test-utils": "^2.4.3", + "@vue/tsconfig": "^0.5.1", + "autoprefixer": "^10.4.16", + "eslint": "^8.56.0", + "eslint-plugin-vue": "^9.20.1", + "husky": "^9.0.11", + "jsdom": "^24.0.0", + "lint-staged": "^15.2.2", + "npm-run-all": "^4.1.5", + "postcss": "^8.4.35", + "prettier": "^3.2.5", + "prettier-plugin-tailwindcss": "^0.5.11", + "tailwindcss": "^3.4.1", + "typescript": "^5.3.3", + "vite": "^5.1.1", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" } } diff --git a/report-viewer/playwright.config.ts b/report-viewer/playwright.config.ts new file mode 100644 index 000000000..be79ec39e --- /dev/null +++ b/report-viewer/playwright.config.ts @@ -0,0 +1,115 @@ +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, + toMatchSnapshot: { + maxDiffPixelRatio: 0.01 + } + }, + /* 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:8080', + + /* 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: true + }, + + /* 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: 'vite preview --port 8080', + port: 8080, + 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..f352008d9 --- /dev/null +++ b/report-viewer/postcss.config.js @@ -0,0 +1,7 @@ +/* eslint-env node */ +export default { + 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..c5b5da48c 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/ClusterGraph.vue b/report-viewer/src/components/ClusterGraph.vue new file mode 100644 index 000000000..60713892f --- /dev/null +++ b/report-viewer/src/components/ClusterGraph.vue @@ -0,0 +1,393 @@ + + + diff --git a/report-viewer/src/components/ClusterRadarChart.vue b/report-viewer/src/components/ClusterRadarChart.vue index e593cccc4..dbe8136b1 100644 --- a/report-viewer/src/components/ClusterRadarChart.vue +++ b/report-viewer/src/components/ClusterRadarChart.vue @@ -3,125 +3,145 @@ participants in the cluster. --> - +const dataSet = computed(() => { + let data = new Array() + props.cluster.members + .get(idOfShownSubmission.value) + ?.forEach((m) => data.push(+(m.similarity * 100).toFixed(2))) + return data +}) - +const radarChartOptions = computed(() => { + return { + 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: labels.value, + datasets: [ + { + ...radarChartStyle, + label: store().getDisplayName(idOfShownSubmission.value), + data: dataSet.value + } + ] + } +}) + 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 deleted file mode 100644 index 3c4ad269b..000000000 --- a/report-viewer/src/components/CodePanel.vue +++ /dev/null @@ -1,249 +0,0 @@ - - - - - - diff --git a/report-viewer/src/components/ComparisonTableFilter.vue b/report-viewer/src/components/ComparisonTableFilter.vue new file mode 100644 index 000000000..646a7d2c7 --- /dev/null +++ b/report-viewer/src/components/ComparisonTableFilter.vue @@ -0,0 +1,123 @@ + + + diff --git a/report-viewer/src/components/ComparisonsTable.vue b/report-viewer/src/components/ComparisonsTable.vue index 3b085b5e5..f5607b316 100644 --- a/report-viewer/src/components/ComparisonsTable.vue +++ b/report-viewer/src/components/ComparisonsTable.vue @@ -2,350 +2,332 @@ Table which display all of the comparisons with their participating ids and similarity percentage for the selected metric. -->